c51df3823cfa926e5b2aafa21277fbcb5aefdbf9
[libguestfs.git] / src / generator.ml
1 #!/usr/bin/env ocaml
2 (* libguestfs
3  * Copyright (C) 2009-2010 Red Hat Inc.
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18  *)
19
20 (* This script generates a large amount of code and documentation for
21  * all the daemon actions.
22  *
23  * To add a new action there are only two files you need to change,
24  * this one to describe the interface (see the big table of
25  * 'daemon_functions' below), and daemon/<somefile>.c to write the
26  * implementation.
27  *
28  * After editing this file, run it (./src/generator.ml) to regenerate
29  * all the output files.  'make' will rerun this automatically when
30  * necessary.  Note that if you are using a separate build directory
31  * you must run generator.ml from the _source_ directory.
32  *
33  * IMPORTANT: This script should NOT print any warnings.  If it prints
34  * warnings, you should treat them as errors.
35  *
36  * OCaml tips:
37  * (1) In emacs, install tuareg-mode to display and format OCaml code
38  * correctly.  'vim' comes with a good OCaml editing mode by default.
39  * (2) Read the resources at http://ocaml-tutorial.org/
40  *)
41
42 #load "unix.cma";;
43 #load "str.cma";;
44 #directory "+xml-light";;
45 #directory "+../pkg-lib/xml-light";; (* for GODI users *)
46 #load "xml-light.cma";;
47
48 open Unix
49 open Printf
50
51 type style = ret * args
52 and ret =
53     (* "RErr" as a return value means an int used as a simple error
54      * indication, ie. 0 or -1.
55      *)
56   | RErr
57
58     (* "RInt" as a return value means an int which is -1 for error
59      * or any value >= 0 on success.  Only use this for smallish
60      * positive ints (0 <= i < 2^30).
61      *)
62   | RInt of string
63
64     (* "RInt64" is the same as RInt, but is guaranteed to be able
65      * to return a full 64 bit value, _except_ that -1 means error
66      * (so -1 cannot be a valid, non-error return value).
67      *)
68   | RInt64 of string
69
70     (* "RBool" is a bool return value which can be true/false or
71      * -1 for error.
72      *)
73   | RBool of string
74
75     (* "RConstString" is a string that refers to a constant value.
76      * The return value must NOT be NULL (since NULL indicates
77      * an error).
78      *
79      * Try to avoid using this.  In particular you cannot use this
80      * for values returned from the daemon, because there is no
81      * thread-safe way to return them in the C API.
82      *)
83   | RConstString of string
84
85     (* "RConstOptString" is an even more broken version of
86      * "RConstString".  The returned string may be NULL and there
87      * is no way to return an error indication.  Avoid using this!
88      *)
89   | RConstOptString of string
90
91     (* "RString" is a returned string.  It must NOT be NULL, since
92      * a NULL return indicates an error.  The caller frees this.
93      *)
94   | RString of string
95
96     (* "RStringList" is a list of strings.  No string in the list
97      * can be NULL.  The caller frees the strings and the array.
98      *)
99   | RStringList of string
100
101     (* "RStruct" is a function which returns a single named structure
102      * or an error indication (in C, a struct, and in other languages
103      * with varying representations, but usually very efficient).  See
104      * after the function list below for the structures.
105      *)
106   | RStruct of string * string          (* name of retval, name of struct *)
107
108     (* "RStructList" is a function which returns either a list/array
109      * of structures (could be zero-length), or an error indication.
110      *)
111   | RStructList of string * string      (* name of retval, name of struct *)
112
113     (* Key-value pairs of untyped strings.  Turns into a hashtable or
114      * dictionary in languages which support it.  DON'T use this as a
115      * general "bucket" for results.  Prefer a stronger typed return
116      * value if one is available, or write a custom struct.  Don't use
117      * this if the list could potentially be very long, since it is
118      * inefficient.  Keys should be unique.  NULLs are not permitted.
119      *)
120   | RHashtable of string
121
122     (* "RBufferOut" is handled almost exactly like RString, but
123      * it allows the string to contain arbitrary 8 bit data including
124      * ASCII NUL.  In the C API this causes an implicit extra parameter
125      * to be added of type <size_t *size_r>.  The extra parameter
126      * returns the actual size of the return buffer in bytes.
127      *
128      * Other programming languages support strings with arbitrary 8 bit
129      * data.
130      *
131      * At the RPC layer we have to use the opaque<> type instead of
132      * string<>.  Returned data is still limited to the max message
133      * size (ie. ~ 2 MB).
134      *)
135   | RBufferOut of string
136
137 and args = argt list    (* Function parameters, guestfs handle is implicit. *)
138
139     (* Note in future we should allow a "variable args" parameter as
140      * the final parameter, to allow commands like
141      *   chmod mode file [file(s)...]
142      * This is not implemented yet, but many commands (such as chmod)
143      * are currently defined with the argument order keeping this future
144      * possibility in mind.
145      *)
146 and argt =
147   | String of string    (* const char *name, cannot be NULL *)
148   | Device of string    (* /dev device name, cannot be NULL *)
149   | Pathname of string  (* file name, cannot be NULL *)
150   | Dev_or_Path of string (* /dev device name or Pathname, cannot be NULL *)
151   | OptString of string (* const char *name, may be NULL *)
152   | StringList of string(* list of strings (each string cannot be NULL) *)
153   | DeviceList of string(* list of Device names (each cannot be NULL) *)
154   | Bool of string      (* boolean *)
155   | Int of string       (* int (smallish ints, signed, <= 31 bits) *)
156   | Int64 of string     (* any 64 bit int *)
157     (* These are treated as filenames (simple string parameters) in
158      * the C API and bindings.  But in the RPC protocol, we transfer
159      * the actual file content up to or down from the daemon.
160      * FileIn: local machine -> daemon (in request)
161      * FileOut: daemon -> local machine (in reply)
162      * In guestfish (only), the special name "-" means read from
163      * stdin or write to stdout.
164      *)
165   | FileIn of string
166   | FileOut of string
167 (* Not implemented:
168     (* Opaque buffer which can contain arbitrary 8 bit data.
169      * In the C API, this is expressed as <char *, int> pair.
170      * Most other languages have a string type which can contain
171      * ASCII NUL.  We use whatever type is appropriate for each
172      * language.
173      * Buffers are limited by the total message size.  To transfer
174      * large blocks of data, use FileIn/FileOut parameters instead.
175      * To return an arbitrary buffer, use RBufferOut.
176      *)
177   | BufferIn of string
178 *)
179
180 type flags =
181   | ProtocolLimitWarning  (* display warning about protocol size limits *)
182   | DangerWillRobinson    (* flags particularly dangerous commands *)
183   | FishAlias of string   (* provide an alias for this cmd in guestfish *)
184   | FishAction of string  (* call this function in guestfish *)
185   | FishOutput of fish_output_t (* how to display output in guestfish *)
186   | NotInFish             (* do not export via guestfish *)
187   | NotInDocs             (* do not add this function to documentation *)
188   | DeprecatedBy of string (* function is deprecated, use .. instead *)
189   | Optional of string    (* function is part of an optional group *)
190
191 and fish_output_t =
192   | FishOutputOctal       (* for int return, print in octal *)
193   | FishOutputHexadecimal (* for int return, print in hex *)
194
195 (* You can supply zero or as many tests as you want per API call.
196  *
197  * Note that the test environment has 3 block devices, of size 500MB,
198  * 50MB and 10MB (respectively /dev/sda, /dev/sdb, /dev/sdc), and
199  * a fourth ISO block device with some known files on it (/dev/sdd).
200  *
201  * Note for partitioning purposes, the 500MB device has 1015 cylinders.
202  * Number of cylinders was 63 for IDE emulated disks with precisely
203  * the same size.  How exactly this is calculated is a mystery.
204  *
205  * The ISO block device (/dev/sdd) comes from images/test.iso.
206  *
207  * To be able to run the tests in a reasonable amount of time,
208  * the virtual machine and block devices are reused between tests.
209  * So don't try testing kill_subprocess :-x
210  *
211  * Between each test we blockdev-setrw, umount-all, lvm-remove-all.
212  *
213  * Don't assume anything about the previous contents of the block
214  * devices.  Use 'Init*' to create some initial scenarios.
215  *
216  * You can add a prerequisite clause to any individual test.  This
217  * is a run-time check, which, if it fails, causes the test to be
218  * skipped.  Useful if testing a command which might not work on
219  * all variations of libguestfs builds.  A test that has prerequisite
220  * of 'Always' is run unconditionally.
221  *
222  * In addition, packagers can skip individual tests by setting the
223  * environment variables:     eg:
224  *   SKIP_TEST_<CMD>_<NUM>=1  SKIP_TEST_COMMAND_3=1  (skips test #3 of command)
225  *   SKIP_TEST_<CMD>=1        SKIP_TEST_ZEROFREE=1   (skips all zerofree tests)
226  *)
227 type tests = (test_init * test_prereq * test) list
228 and test =
229     (* Run the command sequence and just expect nothing to fail. *)
230   | TestRun of seq
231
232     (* Run the command sequence and expect the output of the final
233      * command to be the string.
234      *)
235   | TestOutput of seq * string
236
237     (* Run the command sequence and expect the output of the final
238      * command to be the list of strings.
239      *)
240   | TestOutputList of seq * string list
241
242     (* Run the command sequence and expect the output of the final
243      * command to be the list of block devices (could be either
244      * "/dev/sd.." or "/dev/hd.." form - we don't check the 5th
245      * character of each string).
246      *)
247   | TestOutputListOfDevices of seq * string list
248
249     (* Run the command sequence and expect the output of the final
250      * command to be the integer.
251      *)
252   | TestOutputInt of seq * int
253
254     (* Run the command sequence and expect the output of the final
255      * command to be <op> <int>, eg. ">=", "1".
256      *)
257   | TestOutputIntOp of seq * string * int
258
259     (* Run the command sequence and expect the output of the final
260      * command to be a true value (!= 0 or != NULL).
261      *)
262   | TestOutputTrue of seq
263
264     (* Run the command sequence and expect the output of the final
265      * command to be a false value (== 0 or == NULL, but not an error).
266      *)
267   | TestOutputFalse of seq
268
269     (* Run the command sequence and expect the output of the final
270      * command to be a list of the given length (but don't care about
271      * content).
272      *)
273   | TestOutputLength of seq * int
274
275     (* Run the command sequence and expect the output of the final
276      * command to be a buffer (RBufferOut), ie. string + size.
277      *)
278   | TestOutputBuffer of seq * string
279
280     (* Run the command sequence and expect the output of the final
281      * command to be a structure.
282      *)
283   | TestOutputStruct of seq * test_field_compare list
284
285     (* Run the command sequence and expect the final command (only)
286      * to fail.
287      *)
288   | TestLastFail of seq
289
290 and test_field_compare =
291   | CompareWithInt of string * int
292   | CompareWithIntOp of string * string * int
293   | CompareWithString of string * string
294   | CompareFieldsIntEq of string * string
295   | CompareFieldsStrEq of string * string
296
297 (* Test prerequisites. *)
298 and test_prereq =
299     (* Test always runs. *)
300   | Always
301
302     (* Test is currently disabled - eg. it fails, or it tests some
303      * unimplemented feature.
304      *)
305   | Disabled
306
307     (* 'string' is some C code (a function body) that should return
308      * true or false.  The test will run if the code returns true.
309      *)
310   | If of string
311
312     (* As for 'If' but the test runs _unless_ the code returns true. *)
313   | Unless of string
314
315 (* Some initial scenarios for testing. *)
316 and test_init =
317     (* Do nothing, block devices could contain random stuff including
318      * LVM PVs, and some filesystems might be mounted.  This is usually
319      * a bad idea.
320      *)
321   | InitNone
322
323     (* Block devices are empty and no filesystems are mounted. *)
324   | InitEmpty
325
326     (* /dev/sda contains a single partition /dev/sda1, with random
327      * content.  /dev/sdb and /dev/sdc may have random content.
328      * No LVM.
329      *)
330   | InitPartition
331
332     (* /dev/sda contains a single partition /dev/sda1, which is formatted
333      * as ext2, empty [except for lost+found] and mounted on /.
334      * /dev/sdb and /dev/sdc may have random content.
335      * No LVM.
336      *)
337   | InitBasicFS
338
339     (* /dev/sda:
340      *   /dev/sda1 (is a PV):
341      *     /dev/VG/LV (size 8MB):
342      *       formatted as ext2, empty [except for lost+found], mounted on /
343      * /dev/sdb and /dev/sdc may have random content.
344      *)
345   | InitBasicFSonLVM
346
347     (* /dev/sdd (the ISO, see images/ directory in source)
348      * is mounted on /
349      *)
350   | InitISOFS
351
352 (* Sequence of commands for testing. *)
353 and seq = cmd list
354 and cmd = string list
355
356 (* Note about long descriptions: When referring to another
357  * action, use the format C<guestfs_other> (ie. the full name of
358  * the C function).  This will be replaced as appropriate in other
359  * language bindings.
360  *
361  * Apart from that, long descriptions are just perldoc paragraphs.
362  *)
363
364 (* Generate a random UUID (used in tests). *)
365 let uuidgen () =
366   let chan = open_process_in "uuidgen" in
367   let uuid = input_line chan in
368   (match close_process_in chan with
369    | WEXITED 0 -> ()
370    | WEXITED _ ->
371        failwith "uuidgen: process exited with non-zero status"
372    | WSIGNALED _ | WSTOPPED _ ->
373        failwith "uuidgen: process signalled or stopped by signal"
374   );
375   uuid
376
377 (* These test functions are used in the language binding tests. *)
378
379 let test_all_args = [
380   String "str";
381   OptString "optstr";
382   StringList "strlist";
383   Bool "b";
384   Int "integer";
385   Int64 "integer64";
386   FileIn "filein";
387   FileOut "fileout";
388 ]
389
390 let test_all_rets = [
391   (* except for RErr, which is tested thoroughly elsewhere *)
392   "test0rint",         RInt "valout";
393   "test0rint64",       RInt64 "valout";
394   "test0rbool",        RBool "valout";
395   "test0rconststring", RConstString "valout";
396   "test0rconstoptstring", RConstOptString "valout";
397   "test0rstring",      RString "valout";
398   "test0rstringlist",  RStringList "valout";
399   "test0rstruct",      RStruct ("valout", "lvm_pv");
400   "test0rstructlist",  RStructList ("valout", "lvm_pv");
401   "test0rhashtable",   RHashtable "valout";
402 ]
403
404 let test_functions = [
405   ("test0", (RErr, test_all_args), -1, [NotInFish; NotInDocs],
406    [],
407    "internal test function - do not use",
408    "\
409 This is an internal test function which is used to test whether
410 the automatically generated bindings can handle every possible
411 parameter type correctly.
412
413 It echos the contents of each parameter to stdout.
414
415 You probably don't want to call this function.");
416 ] @ List.flatten (
417   List.map (
418     fun (name, ret) ->
419       [(name, (ret, [String "val"]), -1, [NotInFish; NotInDocs],
420         [],
421         "internal test function - do not use",
422         "\
423 This is an internal test function which is used to test whether
424 the automatically generated bindings can handle every possible
425 return type correctly.
426
427 It converts string C<val> to the return type.
428
429 You probably don't want to call this function.");
430        (name ^ "err", (ret, []), -1, [NotInFish; NotInDocs],
431         [],
432         "internal test function - do not use",
433         "\
434 This is an internal test function which is used to test whether
435 the automatically generated bindings can handle every possible
436 return type correctly.
437
438 This function always returns an error.
439
440 You probably don't want to call this function.")]
441   ) test_all_rets
442 )
443
444 (* non_daemon_functions are any functions which don't get processed
445  * in the daemon, eg. functions for setting and getting local
446  * configuration values.
447  *)
448
449 let non_daemon_functions = test_functions @ [
450   ("launch", (RErr, []), -1, [FishAlias "run"; FishAction "launch"],
451    [],
452    "launch the qemu subprocess",
453    "\
454 Internally libguestfs is implemented by running a virtual machine
455 using L<qemu(1)>.
456
457 You should call this after configuring the handle
458 (eg. adding drives) but before performing any actions.");
459
460   ("wait_ready", (RErr, []), -1, [NotInFish],
461    [],
462    "wait until the qemu subprocess launches (no op)",
463    "\
464 This function is a no op.
465
466 In versions of the API E<lt> 1.0.71 you had to call this function
467 just after calling C<guestfs_launch> to wait for the launch
468 to complete.  However this is no longer necessary because
469 C<guestfs_launch> now does the waiting.
470
471 If you see any calls to this function in code then you can just
472 remove them, unless you want to retain compatibility with older
473 versions of the API.");
474
475   ("kill_subprocess", (RErr, []), -1, [],
476    [],
477    "kill the qemu subprocess",
478    "\
479 This kills the qemu subprocess.  You should never need to call this.");
480
481   ("add_drive", (RErr, [String "filename"]), -1, [FishAlias "add"],
482    [],
483    "add an image to examine or modify",
484    "\
485 This function adds a virtual machine disk image C<filename> to the
486 guest.  The first time you call this function, the disk appears as IDE
487 disk 0 (C</dev/sda>) in the guest, the second time as C</dev/sdb>, and
488 so on.
489
490 You don't necessarily need to be root when using libguestfs.  However
491 you obviously do need sufficient permissions to access the filename
492 for whatever operations you want to perform (ie. read access if you
493 just want to read the image or write access if you want to modify the
494 image).
495
496 This is equivalent to the qemu parameter
497 C<-drive file=filename,cache=off,if=...>.
498
499 C<cache=off> is omitted in cases where it is not supported by
500 the underlying filesystem.
501
502 C<if=...> is set at compile time by the configuration option
503 C<./configure --with-drive-if=...>.  In the rare case where you
504 might need to change this at run time, use C<guestfs_add_drive_with_if>
505 or C<guestfs_add_drive_ro_with_if>.
506
507 Note that this call checks for the existence of C<filename>.  This
508 stops you from specifying other types of drive which are supported
509 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
510 the general C<guestfs_config> call instead.");
511
512   ("add_cdrom", (RErr, [String "filename"]), -1, [FishAlias "cdrom"],
513    [],
514    "add a CD-ROM disk image to examine",
515    "\
516 This function adds a virtual CD-ROM disk image to the guest.
517
518 This is equivalent to the qemu parameter C<-cdrom filename>.
519
520 Notes:
521
522 =over 4
523
524 =item *
525
526 This call checks for the existence of C<filename>.  This
527 stops you from specifying other types of drive which are supported
528 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
529 the general C<guestfs_config> call instead.
530
531 =item *
532
533 If you just want to add an ISO file (often you use this as an
534 efficient way to transfer large files into the guest), then you
535 should probably use C<guestfs_add_drive_ro> instead.
536
537 =back");
538
539   ("add_drive_ro", (RErr, [String "filename"]), -1, [FishAlias "add-ro"],
540    [],
541    "add a drive in snapshot mode (read-only)",
542    "\
543 This adds a drive in snapshot mode, making it effectively
544 read-only.
545
546 Note that writes to the device are allowed, and will be seen for
547 the duration of the guestfs handle, but they are written
548 to a temporary file which is discarded as soon as the guestfs
549 handle is closed.  We don't currently have any method to enable
550 changes to be committed, although qemu can support this.
551
552 This is equivalent to the qemu parameter
553 C<-drive file=filename,snapshot=on,readonly=on,if=...>.
554
555 C<if=...> is set at compile time by the configuration option
556 C<./configure --with-drive-if=...>.  In the rare case where you
557 might need to change this at run time, use C<guestfs_add_drive_with_if>
558 or C<guestfs_add_drive_ro_with_if>.
559
560 C<readonly=on> is only added where qemu supports this option.
561
562 Note that this call checks for the existence of C<filename>.  This
563 stops you from specifying other types of drive which are supported
564 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
565 the general C<guestfs_config> call instead.");
566
567   ("config", (RErr, [String "qemuparam"; OptString "qemuvalue"]), -1, [],
568    [],
569    "add qemu parameters",
570    "\
571 This can be used to add arbitrary qemu command line parameters
572 of the form C<-param value>.  Actually it's not quite arbitrary - we
573 prevent you from setting some parameters which would interfere with
574 parameters that we use.
575
576 The first character of C<param> string must be a C<-> (dash).
577
578 C<value> can be NULL.");
579
580   ("set_qemu", (RErr, [String "qemu"]), -1, [FishAlias "qemu"],
581    [],
582    "set the qemu binary",
583    "\
584 Set the qemu binary that we will use.
585
586 The default is chosen when the library was compiled by the
587 configure script.
588
589 You can also override this by setting the C<LIBGUESTFS_QEMU>
590 environment variable.
591
592 Setting C<qemu> to C<NULL> restores the default qemu binary.
593
594 Note that you should call this function as early as possible
595 after creating the handle.  This is because some pre-launch
596 operations depend on testing qemu features (by running C<qemu -help>).
597 If the qemu binary changes, we don't retest features, and
598 so you might see inconsistent results.  Using the environment
599 variable C<LIBGUESTFS_QEMU> is safest of all since that picks
600 the qemu binary at the same time as the handle is created.");
601
602   ("get_qemu", (RConstString "qemu", []), -1, [],
603    [InitNone, Always, TestRun (
604       [["get_qemu"]])],
605    "get the qemu binary",
606    "\
607 Return the current qemu binary.
608
609 This is always non-NULL.  If it wasn't set already, then this will
610 return the default qemu binary name.");
611
612   ("set_path", (RErr, [String "searchpath"]), -1, [FishAlias "path"],
613    [],
614    "set the search path",
615    "\
616 Set the path that libguestfs searches for kernel and initrd.img.
617
618 The default is C<$libdir/guestfs> unless overridden by setting
619 C<LIBGUESTFS_PATH> environment variable.
620
621 Setting C<path> to C<NULL> restores the default path.");
622
623   ("get_path", (RConstString "path", []), -1, [],
624    [InitNone, Always, TestRun (
625       [["get_path"]])],
626    "get the search path",
627    "\
628 Return the current search path.
629
630 This is always non-NULL.  If it wasn't set already, then this will
631 return the default path.");
632
633   ("set_append", (RErr, [OptString "append"]), -1, [FishAlias "append"],
634    [],
635    "add options to kernel command line",
636    "\
637 This function is used to add additional options to the
638 guest kernel command line.
639
640 The default is C<NULL> unless overridden by setting
641 C<LIBGUESTFS_APPEND> environment variable.
642
643 Setting C<append> to C<NULL> means I<no> additional options
644 are passed (libguestfs always adds a few of its own).");
645
646   ("get_append", (RConstOptString "append", []), -1, [],
647    (* This cannot be tested with the current framework.  The
648     * function can return NULL in normal operations, which the
649     * test framework interprets as an error.
650     *)
651    [],
652    "get the additional kernel options",
653    "\
654 Return the additional kernel options which are added to the
655 guest kernel command line.
656
657 If C<NULL> then no options are added.");
658
659   ("set_autosync", (RErr, [Bool "autosync"]), -1, [FishAlias "autosync"],
660    [],
661    "set autosync mode",
662    "\
663 If C<autosync> is true, this enables autosync.  Libguestfs will make a
664 best effort attempt to run C<guestfs_umount_all> followed by
665 C<guestfs_sync> when the handle is closed
666 (also if the program exits without closing handles).
667
668 This is disabled by default (except in guestfish where it is
669 enabled by default).");
670
671   ("get_autosync", (RBool "autosync", []), -1, [],
672    [InitNone, Always, TestRun (
673       [["get_autosync"]])],
674    "get autosync mode",
675    "\
676 Get the autosync flag.");
677
678   ("set_verbose", (RErr, [Bool "verbose"]), -1, [FishAlias "verbose"],
679    [],
680    "set verbose mode",
681    "\
682 If C<verbose> is true, this turns on verbose messages (to C<stderr>).
683
684 Verbose messages are disabled unless the environment variable
685 C<LIBGUESTFS_DEBUG> is defined and set to C<1>.");
686
687   ("get_verbose", (RBool "verbose", []), -1, [],
688    [],
689    "get verbose mode",
690    "\
691 This returns the verbose messages flag.");
692
693   ("is_ready", (RBool "ready", []), -1, [],
694    [InitNone, Always, TestOutputTrue (
695       [["is_ready"]])],
696    "is ready to accept commands",
697    "\
698 This returns true iff this handle is ready to accept commands
699 (in the C<READY> state).
700
701 For more information on states, see L<guestfs(3)>.");
702
703   ("is_config", (RBool "config", []), -1, [],
704    [InitNone, Always, TestOutputFalse (
705       [["is_config"]])],
706    "is in configuration state",
707    "\
708 This returns true iff this handle is being configured
709 (in the C<CONFIG> state).
710
711 For more information on states, see L<guestfs(3)>.");
712
713   ("is_launching", (RBool "launching", []), -1, [],
714    [InitNone, Always, TestOutputFalse (
715       [["is_launching"]])],
716    "is launching subprocess",
717    "\
718 This returns true iff this handle is launching the subprocess
719 (in the C<LAUNCHING> state).
720
721 For more information on states, see L<guestfs(3)>.");
722
723   ("is_busy", (RBool "busy", []), -1, [],
724    [InitNone, Always, TestOutputFalse (
725       [["is_busy"]])],
726    "is busy processing a command",
727    "\
728 This returns true iff this handle is busy processing a command
729 (in the C<BUSY> state).
730
731 For more information on states, see L<guestfs(3)>.");
732
733   ("get_state", (RInt "state", []), -1, [],
734    [],
735    "get the current state",
736    "\
737 This returns the current state as an opaque integer.  This is
738 only useful for printing debug and internal error messages.
739
740 For more information on states, see L<guestfs(3)>.");
741
742   ("set_memsize", (RErr, [Int "memsize"]), -1, [FishAlias "memsize"],
743    [InitNone, Always, TestOutputInt (
744       [["set_memsize"; "500"];
745        ["get_memsize"]], 500)],
746    "set memory allocated to the qemu subprocess",
747    "\
748 This sets the memory size in megabytes allocated to the
749 qemu subprocess.  This only has any effect if called before
750 C<guestfs_launch>.
751
752 You can also change this by setting the environment
753 variable C<LIBGUESTFS_MEMSIZE> before the handle is
754 created.
755
756 For more information on the architecture of libguestfs,
757 see L<guestfs(3)>.");
758
759   ("get_memsize", (RInt "memsize", []), -1, [],
760    [InitNone, Always, TestOutputIntOp (
761       [["get_memsize"]], ">=", 256)],
762    "get memory allocated to the qemu subprocess",
763    "\
764 This gets the memory size in megabytes allocated to the
765 qemu subprocess.
766
767 If C<guestfs_set_memsize> was not called
768 on this handle, and if C<LIBGUESTFS_MEMSIZE> was not set,
769 then this returns the compiled-in default value for memsize.
770
771 For more information on the architecture of libguestfs,
772 see L<guestfs(3)>.");
773
774   ("get_pid", (RInt "pid", []), -1, [FishAlias "pid"],
775    [InitNone, Always, TestOutputIntOp (
776       [["get_pid"]], ">=", 1)],
777    "get PID of qemu subprocess",
778    "\
779 Return the process ID of the qemu subprocess.  If there is no
780 qemu subprocess, then this will return an error.
781
782 This is an internal call used for debugging and testing.");
783
784   ("version", (RStruct ("version", "version"), []), -1, [],
785    [InitNone, Always, TestOutputStruct (
786       [["version"]], [CompareWithInt ("major", 1)])],
787    "get the library version number",
788    "\
789 Return the libguestfs version number that the program is linked
790 against.
791
792 Note that because of dynamic linking this is not necessarily
793 the version of libguestfs that you compiled against.  You can
794 compile the program, and then at runtime dynamically link
795 against a completely different C<libguestfs.so> library.
796
797 This call was added in version C<1.0.58>.  In previous
798 versions of libguestfs there was no way to get the version
799 number.  From C code you can use ELF weak linking tricks to find out if
800 this symbol exists (if it doesn't, then it's an earlier version).
801
802 The call returns a structure with four elements.  The first
803 three (C<major>, C<minor> and C<release>) are numbers and
804 correspond to the usual version triplet.  The fourth element
805 (C<extra>) is a string and is normally empty, but may be
806 used for distro-specific information.
807
808 To construct the original version string:
809 C<$major.$minor.$release$extra>
810
811 I<Note:> Don't use this call to test for availability
812 of features.  Distro backports makes this unreliable.  Use
813 C<guestfs_available> instead.");
814
815   ("set_selinux", (RErr, [Bool "selinux"]), -1, [FishAlias "selinux"],
816    [InitNone, Always, TestOutputTrue (
817       [["set_selinux"; "true"];
818        ["get_selinux"]])],
819    "set SELinux enabled or disabled at appliance boot",
820    "\
821 This sets the selinux flag that is passed to the appliance
822 at boot time.  The default is C<selinux=0> (disabled).
823
824 Note that if SELinux is enabled, it is always in
825 Permissive mode (C<enforcing=0>).
826
827 For more information on the architecture of libguestfs,
828 see L<guestfs(3)>.");
829
830   ("get_selinux", (RBool "selinux", []), -1, [],
831    [],
832    "get SELinux enabled flag",
833    "\
834 This returns the current setting of the selinux flag which
835 is passed to the appliance at boot time.  See C<guestfs_set_selinux>.
836
837 For more information on the architecture of libguestfs,
838 see L<guestfs(3)>.");
839
840   ("set_trace", (RErr, [Bool "trace"]), -1, [FishAlias "trace"],
841    [InitNone, Always, TestOutputFalse (
842       [["set_trace"; "false"];
843        ["get_trace"]])],
844    "enable or disable command traces",
845    "\
846 If the command trace flag is set to 1, then commands are
847 printed on stdout before they are executed in a format
848 which is very similar to the one used by guestfish.  In
849 other words, you can run a program with this enabled, and
850 you will get out a script which you can feed to guestfish
851 to perform the same set of actions.
852
853 If you want to trace C API calls into libguestfs (and
854 other libraries) then possibly a better way is to use
855 the external ltrace(1) command.
856
857 Command traces are disabled unless the environment variable
858 C<LIBGUESTFS_TRACE> is defined and set to C<1>.");
859
860   ("get_trace", (RBool "trace", []), -1, [],
861    [],
862    "get command trace enabled flag",
863    "\
864 Return the command trace flag.");
865
866   ("set_direct", (RErr, [Bool "direct"]), -1, [FishAlias "direct"],
867    [InitNone, Always, TestOutputFalse (
868       [["set_direct"; "false"];
869        ["get_direct"]])],
870    "enable or disable direct appliance mode",
871    "\
872 If the direct appliance mode flag is enabled, then stdin and
873 stdout are passed directly through to the appliance once it
874 is launched.
875
876 One consequence of this is that log messages aren't caught
877 by the library and handled by C<guestfs_set_log_message_callback>,
878 but go straight to stdout.
879
880 You probably don't want to use this unless you know what you
881 are doing.
882
883 The default is disabled.");
884
885   ("get_direct", (RBool "direct", []), -1, [],
886    [],
887    "get direct appliance mode flag",
888    "\
889 Return the direct appliance mode flag.");
890
891   ("set_recovery_proc", (RErr, [Bool "recoveryproc"]), -1, [FishAlias "recovery-proc"],
892    [InitNone, Always, TestOutputTrue (
893       [["set_recovery_proc"; "true"];
894        ["get_recovery_proc"]])],
895    "enable or disable the recovery process",
896    "\
897 If this is called with the parameter C<false> then
898 C<guestfs_launch> does not create a recovery process.  The
899 purpose of the recovery process is to stop runaway qemu
900 processes in the case where the main program aborts abruptly.
901
902 This only has any effect if called before C<guestfs_launch>,
903 and the default is true.
904
905 About the only time when you would want to disable this is
906 if the main process will fork itself into the background
907 (\"daemonize\" itself).  In this case the recovery process
908 thinks that the main program has disappeared and so kills
909 qemu, which is not very helpful.");
910
911   ("get_recovery_proc", (RBool "recoveryproc", []), -1, [],
912    [],
913    "get recovery process enabled flag",
914    "\
915 Return the recovery process enabled flag.");
916
917   ("add_drive_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
918    [],
919    "add a drive specifying the QEMU block emulation to use",
920    "\
921 This is the same as C<guestfs_add_drive> but it allows you
922 to specify the QEMU interface emulation to use at run time.");
923
924   ("add_drive_ro_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
925    [],
926    "add a drive read-only specifying the QEMU block emulation to use",
927    "\
928 This is the same as C<guestfs_add_drive_ro> but it allows you
929 to specify the QEMU interface emulation to use at run time.");
930
931 ]
932
933 (* daemon_functions are any functions which cause some action
934  * to take place in the daemon.
935  *)
936
937 let daemon_functions = [
938   ("mount", (RErr, [Device "device"; String "mountpoint"]), 1, [],
939    [InitEmpty, Always, TestOutput (
940       [["part_disk"; "/dev/sda"; "mbr"];
941        ["mkfs"; "ext2"; "/dev/sda1"];
942        ["mount"; "/dev/sda1"; "/"];
943        ["write_file"; "/new"; "new file contents"; "0"];
944        ["cat"; "/new"]], "new file contents")],
945    "mount a guest disk at a position in the filesystem",
946    "\
947 Mount a guest disk at a position in the filesystem.  Block devices
948 are named C</dev/sda>, C</dev/sdb> and so on, as they were added to
949 the guest.  If those block devices contain partitions, they will have
950 the usual names (eg. C</dev/sda1>).  Also LVM C</dev/VG/LV>-style
951 names can be used.
952
953 The rules are the same as for L<mount(2)>:  A filesystem must
954 first be mounted on C</> before others can be mounted.  Other
955 filesystems can only be mounted on directories which already
956 exist.
957
958 The mounted filesystem is writable, if we have sufficient permissions
959 on the underlying device.
960
961 The filesystem options C<sync> and C<noatime> are set with this
962 call, in order to improve reliability.");
963
964   ("sync", (RErr, []), 2, [],
965    [ InitEmpty, Always, TestRun [["sync"]]],
966    "sync disks, writes are flushed through to the disk image",
967    "\
968 This syncs the disk, so that any writes are flushed through to the
969 underlying disk image.
970
971 You should always call this if you have modified a disk image, before
972 closing the handle.");
973
974   ("touch", (RErr, [Pathname "path"]), 3, [],
975    [InitBasicFS, Always, TestOutputTrue (
976       [["touch"; "/new"];
977        ["exists"; "/new"]])],
978    "update file timestamps or create a new file",
979    "\
980 Touch acts like the L<touch(1)> command.  It can be used to
981 update the timestamps on a file, or, if the file does not exist,
982 to create a new zero-length file.");
983
984   ("cat", (RString "content", [Pathname "path"]), 4, [ProtocolLimitWarning],
985    [InitISOFS, Always, TestOutput (
986       [["cat"; "/known-2"]], "abcdef\n")],
987    "list the contents of a file",
988    "\
989 Return the contents of the file named C<path>.
990
991 Note that this function cannot correctly handle binary files
992 (specifically, files containing C<\\0> character which is treated
993 as end of string).  For those you need to use the C<guestfs_read_file>
994 or C<guestfs_download> functions which have a more complex interface.");
995
996   ("ll", (RString "listing", [Pathname "directory"]), 5, [],
997    [], (* XXX Tricky to test because it depends on the exact format
998         * of the 'ls -l' command, which changes between F10 and F11.
999         *)
1000    "list the files in a directory (long format)",
1001    "\
1002 List the files in C<directory> (relative to the root directory,
1003 there is no cwd) in the format of 'ls -la'.
1004
1005 This command is mostly useful for interactive sessions.  It
1006 is I<not> intended that you try to parse the output string.");
1007
1008   ("ls", (RStringList "listing", [Pathname "directory"]), 6, [],
1009    [InitBasicFS, Always, TestOutputList (
1010       [["touch"; "/new"];
1011        ["touch"; "/newer"];
1012        ["touch"; "/newest"];
1013        ["ls"; "/"]], ["lost+found"; "new"; "newer"; "newest"])],
1014    "list the files in a directory",
1015    "\
1016 List the files in C<directory> (relative to the root directory,
1017 there is no cwd).  The '.' and '..' entries are not returned, but
1018 hidden files are shown.
1019
1020 This command is mostly useful for interactive sessions.  Programs
1021 should probably use C<guestfs_readdir> instead.");
1022
1023   ("list_devices", (RStringList "devices", []), 7, [],
1024    [InitEmpty, Always, TestOutputListOfDevices (
1025       [["list_devices"]], ["/dev/sda"; "/dev/sdb"; "/dev/sdc"; "/dev/sdd"])],
1026    "list the block devices",
1027    "\
1028 List all the block devices.
1029
1030 The full block device names are returned, eg. C</dev/sda>");
1031
1032   ("list_partitions", (RStringList "partitions", []), 8, [],
1033    [InitBasicFS, Always, TestOutputListOfDevices (
1034       [["list_partitions"]], ["/dev/sda1"]);
1035     InitEmpty, Always, TestOutputListOfDevices (
1036       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1037        ["list_partitions"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1038    "list the partitions",
1039    "\
1040 List all the partitions detected on all block devices.
1041
1042 The full partition device names are returned, eg. C</dev/sda1>
1043
1044 This does not return logical volumes.  For that you will need to
1045 call C<guestfs_lvs>.");
1046
1047   ("pvs", (RStringList "physvols", []), 9, [Optional "lvm2"],
1048    [InitBasicFSonLVM, Always, TestOutputListOfDevices (
1049       [["pvs"]], ["/dev/sda1"]);
1050     InitEmpty, Always, TestOutputListOfDevices (
1051       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1052        ["pvcreate"; "/dev/sda1"];
1053        ["pvcreate"; "/dev/sda2"];
1054        ["pvcreate"; "/dev/sda3"];
1055        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1056    "list the LVM physical volumes (PVs)",
1057    "\
1058 List all the physical volumes detected.  This is the equivalent
1059 of the L<pvs(8)> command.
1060
1061 This returns a list of just the device names that contain
1062 PVs (eg. C</dev/sda2>).
1063
1064 See also C<guestfs_pvs_full>.");
1065
1066   ("vgs", (RStringList "volgroups", []), 10, [Optional "lvm2"],
1067    [InitBasicFSonLVM, Always, TestOutputList (
1068       [["vgs"]], ["VG"]);
1069     InitEmpty, Always, TestOutputList (
1070       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1071        ["pvcreate"; "/dev/sda1"];
1072        ["pvcreate"; "/dev/sda2"];
1073        ["pvcreate"; "/dev/sda3"];
1074        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1075        ["vgcreate"; "VG2"; "/dev/sda3"];
1076        ["vgs"]], ["VG1"; "VG2"])],
1077    "list the LVM volume groups (VGs)",
1078    "\
1079 List all the volumes groups detected.  This is the equivalent
1080 of the L<vgs(8)> command.
1081
1082 This returns a list of just the volume group names that were
1083 detected (eg. C<VolGroup00>).
1084
1085 See also C<guestfs_vgs_full>.");
1086
1087   ("lvs", (RStringList "logvols", []), 11, [Optional "lvm2"],
1088    [InitBasicFSonLVM, Always, TestOutputList (
1089       [["lvs"]], ["/dev/VG/LV"]);
1090     InitEmpty, Always, TestOutputList (
1091       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1092        ["pvcreate"; "/dev/sda1"];
1093        ["pvcreate"; "/dev/sda2"];
1094        ["pvcreate"; "/dev/sda3"];
1095        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1096        ["vgcreate"; "VG2"; "/dev/sda3"];
1097        ["lvcreate"; "LV1"; "VG1"; "50"];
1098        ["lvcreate"; "LV2"; "VG1"; "50"];
1099        ["lvcreate"; "LV3"; "VG2"; "50"];
1100        ["lvs"]], ["/dev/VG1/LV1"; "/dev/VG1/LV2"; "/dev/VG2/LV3"])],
1101    "list the LVM logical volumes (LVs)",
1102    "\
1103 List all the logical volumes detected.  This is the equivalent
1104 of the L<lvs(8)> command.
1105
1106 This returns a list of the logical volume device names
1107 (eg. C</dev/VolGroup00/LogVol00>).
1108
1109 See also C<guestfs_lvs_full>.");
1110
1111   ("pvs_full", (RStructList ("physvols", "lvm_pv"), []), 12, [Optional "lvm2"],
1112    [], (* XXX how to test? *)
1113    "list the LVM physical volumes (PVs)",
1114    "\
1115 List all the physical volumes detected.  This is the equivalent
1116 of the L<pvs(8)> command.  The \"full\" version includes all fields.");
1117
1118   ("vgs_full", (RStructList ("volgroups", "lvm_vg"), []), 13, [Optional "lvm2"],
1119    [], (* XXX how to test? *)
1120    "list the LVM volume groups (VGs)",
1121    "\
1122 List all the volumes groups detected.  This is the equivalent
1123 of the L<vgs(8)> command.  The \"full\" version includes all fields.");
1124
1125   ("lvs_full", (RStructList ("logvols", "lvm_lv"), []), 14, [Optional "lvm2"],
1126    [], (* XXX how to test? *)
1127    "list the LVM logical volumes (LVs)",
1128    "\
1129 List all the logical volumes detected.  This is the equivalent
1130 of the L<lvs(8)> command.  The \"full\" version includes all fields.");
1131
1132   ("read_lines", (RStringList "lines", [Pathname "path"]), 15, [],
1133    [InitISOFS, Always, TestOutputList (
1134       [["read_lines"; "/known-4"]], ["abc"; "def"; "ghi"]);
1135     InitISOFS, Always, TestOutputList (
1136       [["read_lines"; "/empty"]], [])],
1137    "read file as lines",
1138    "\
1139 Return the contents of the file named C<path>.
1140
1141 The file contents are returned as a list of lines.  Trailing
1142 C<LF> and C<CRLF> character sequences are I<not> returned.
1143
1144 Note that this function cannot correctly handle binary files
1145 (specifically, files containing C<\\0> character which is treated
1146 as end of line).  For those you need to use the C<guestfs_read_file>
1147 function which has a more complex interface.");
1148
1149   ("aug_init", (RErr, [Pathname "root"; Int "flags"]), 16, [Optional "augeas"],
1150    [], (* XXX Augeas code needs tests. *)
1151    "create a new Augeas handle",
1152    "\
1153 Create a new Augeas handle for editing configuration files.
1154 If there was any previous Augeas handle associated with this
1155 guestfs session, then it is closed.
1156
1157 You must call this before using any other C<guestfs_aug_*>
1158 commands.
1159
1160 C<root> is the filesystem root.  C<root> must not be NULL,
1161 use C</> instead.
1162
1163 The flags are the same as the flags defined in
1164 E<lt>augeas.hE<gt>, the logical I<or> of the following
1165 integers:
1166
1167 =over 4
1168
1169 =item C<AUG_SAVE_BACKUP> = 1
1170
1171 Keep the original file with a C<.augsave> extension.
1172
1173 =item C<AUG_SAVE_NEWFILE> = 2
1174
1175 Save changes into a file with extension C<.augnew>, and
1176 do not overwrite original.  Overrides C<AUG_SAVE_BACKUP>.
1177
1178 =item C<AUG_TYPE_CHECK> = 4
1179
1180 Typecheck lenses (can be expensive).
1181
1182 =item C<AUG_NO_STDINC> = 8
1183
1184 Do not use standard load path for modules.
1185
1186 =item C<AUG_SAVE_NOOP> = 16
1187
1188 Make save a no-op, just record what would have been changed.
1189
1190 =item C<AUG_NO_LOAD> = 32
1191
1192 Do not load the tree in C<guestfs_aug_init>.
1193
1194 =back
1195
1196 To close the handle, you can call C<guestfs_aug_close>.
1197
1198 To find out more about Augeas, see L<http://augeas.net/>.");
1199
1200   ("aug_close", (RErr, []), 26, [Optional "augeas"],
1201    [], (* XXX Augeas code needs tests. *)
1202    "close the current Augeas handle",
1203    "\
1204 Close the current Augeas handle and free up any resources
1205 used by it.  After calling this, you have to call
1206 C<guestfs_aug_init> again before you can use any other
1207 Augeas functions.");
1208
1209   ("aug_defvar", (RInt "nrnodes", [String "name"; OptString "expr"]), 17, [Optional "augeas"],
1210    [], (* XXX Augeas code needs tests. *)
1211    "define an Augeas variable",
1212    "\
1213 Defines an Augeas variable C<name> whose value is the result
1214 of evaluating C<expr>.  If C<expr> is NULL, then C<name> is
1215 undefined.
1216
1217 On success this returns the number of nodes in C<expr>, or
1218 C<0> if C<expr> evaluates to something which is not a nodeset.");
1219
1220   ("aug_defnode", (RStruct ("nrnodescreated", "int_bool"), [String "name"; String "expr"; String "val"]), 18, [Optional "augeas"],
1221    [], (* XXX Augeas code needs tests. *)
1222    "define an Augeas node",
1223    "\
1224 Defines a variable C<name> whose value is the result of
1225 evaluating C<expr>.
1226
1227 If C<expr> evaluates to an empty nodeset, a node is created,
1228 equivalent to calling C<guestfs_aug_set> C<expr>, C<value>.
1229 C<name> will be the nodeset containing that single node.
1230
1231 On success this returns a pair containing the
1232 number of nodes in the nodeset, and a boolean flag
1233 if a node was created.");
1234
1235   ("aug_get", (RString "val", [String "augpath"]), 19, [Optional "augeas"],
1236    [], (* XXX Augeas code needs tests. *)
1237    "look up the value of an Augeas path",
1238    "\
1239 Look up the value associated with C<path>.  If C<path>
1240 matches exactly one node, the C<value> is returned.");
1241
1242   ("aug_set", (RErr, [String "augpath"; String "val"]), 20, [Optional "augeas"],
1243    [], (* XXX Augeas code needs tests. *)
1244    "set Augeas path to value",
1245    "\
1246 Set the value associated with C<path> to C<val>.
1247
1248 In the Augeas API, it is possible to clear a node by setting
1249 the value to NULL.  Due to an oversight in the libguestfs API
1250 you cannot do that with this call.  Instead you must use the
1251 C<guestfs_aug_clear> call.");
1252
1253   ("aug_insert", (RErr, [String "augpath"; String "label"; Bool "before"]), 21, [Optional "augeas"],
1254    [], (* XXX Augeas code needs tests. *)
1255    "insert a sibling Augeas node",
1256    "\
1257 Create a new sibling C<label> for C<path>, inserting it into
1258 the tree before or after C<path> (depending on the boolean
1259 flag C<before>).
1260
1261 C<path> must match exactly one existing node in the tree, and
1262 C<label> must be a label, ie. not contain C</>, C<*> or end
1263 with a bracketed index C<[N]>.");
1264
1265   ("aug_rm", (RInt "nrnodes", [String "augpath"]), 22, [Optional "augeas"],
1266    [], (* XXX Augeas code needs tests. *)
1267    "remove an Augeas path",
1268    "\
1269 Remove C<path> and all of its children.
1270
1271 On success this returns the number of entries which were removed.");
1272
1273   ("aug_mv", (RErr, [String "src"; String "dest"]), 23, [Optional "augeas"],
1274    [], (* XXX Augeas code needs tests. *)
1275    "move Augeas node",
1276    "\
1277 Move the node C<src> to C<dest>.  C<src> must match exactly
1278 one node.  C<dest> is overwritten if it exists.");
1279
1280   ("aug_match", (RStringList "matches", [String "augpath"]), 24, [Optional "augeas"],
1281    [], (* XXX Augeas code needs tests. *)
1282    "return Augeas nodes which match augpath",
1283    "\
1284 Returns a list of paths which match the path expression C<path>.
1285 The returned paths are sufficiently qualified so that they match
1286 exactly one node in the current tree.");
1287
1288   ("aug_save", (RErr, []), 25, [Optional "augeas"],
1289    [], (* XXX Augeas code needs tests. *)
1290    "write all pending Augeas changes to disk",
1291    "\
1292 This writes all pending changes to disk.
1293
1294 The flags which were passed to C<guestfs_aug_init> affect exactly
1295 how files are saved.");
1296
1297   ("aug_load", (RErr, []), 27, [Optional "augeas"],
1298    [], (* XXX Augeas code needs tests. *)
1299    "load files into the tree",
1300    "\
1301 Load files into the tree.
1302
1303 See C<aug_load> in the Augeas documentation for the full gory
1304 details.");
1305
1306   ("aug_ls", (RStringList "matches", [String "augpath"]), 28, [Optional "augeas"],
1307    [], (* XXX Augeas code needs tests. *)
1308    "list Augeas nodes under augpath",
1309    "\
1310 This is just a shortcut for listing C<guestfs_aug_match>
1311 C<path/*> and sorting the resulting nodes into alphabetical order.");
1312
1313   ("rm", (RErr, [Pathname "path"]), 29, [],
1314    [InitBasicFS, Always, TestRun
1315       [["touch"; "/new"];
1316        ["rm"; "/new"]];
1317     InitBasicFS, Always, TestLastFail
1318       [["rm"; "/new"]];
1319     InitBasicFS, Always, TestLastFail
1320       [["mkdir"; "/new"];
1321        ["rm"; "/new"]]],
1322    "remove a file",
1323    "\
1324 Remove the single file C<path>.");
1325
1326   ("rmdir", (RErr, [Pathname "path"]), 30, [],
1327    [InitBasicFS, Always, TestRun
1328       [["mkdir"; "/new"];
1329        ["rmdir"; "/new"]];
1330     InitBasicFS, Always, TestLastFail
1331       [["rmdir"; "/new"]];
1332     InitBasicFS, Always, TestLastFail
1333       [["touch"; "/new"];
1334        ["rmdir"; "/new"]]],
1335    "remove a directory",
1336    "\
1337 Remove the single directory C<path>.");
1338
1339   ("rm_rf", (RErr, [Pathname "path"]), 31, [],
1340    [InitBasicFS, Always, TestOutputFalse
1341       [["mkdir"; "/new"];
1342        ["mkdir"; "/new/foo"];
1343        ["touch"; "/new/foo/bar"];
1344        ["rm_rf"; "/new"];
1345        ["exists"; "/new"]]],
1346    "remove a file or directory recursively",
1347    "\
1348 Remove the file or directory C<path>, recursively removing the
1349 contents if its a directory.  This is like the C<rm -rf> shell
1350 command.");
1351
1352   ("mkdir", (RErr, [Pathname "path"]), 32, [],
1353    [InitBasicFS, Always, TestOutputTrue
1354       [["mkdir"; "/new"];
1355        ["is_dir"; "/new"]];
1356     InitBasicFS, Always, TestLastFail
1357       [["mkdir"; "/new/foo/bar"]]],
1358    "create a directory",
1359    "\
1360 Create a directory named C<path>.");
1361
1362   ("mkdir_p", (RErr, [Pathname "path"]), 33, [],
1363    [InitBasicFS, Always, TestOutputTrue
1364       [["mkdir_p"; "/new/foo/bar"];
1365        ["is_dir"; "/new/foo/bar"]];
1366     InitBasicFS, Always, TestOutputTrue
1367       [["mkdir_p"; "/new/foo/bar"];
1368        ["is_dir"; "/new/foo"]];
1369     InitBasicFS, Always, TestOutputTrue
1370       [["mkdir_p"; "/new/foo/bar"];
1371        ["is_dir"; "/new"]];
1372     (* Regression tests for RHBZ#503133: *)
1373     InitBasicFS, Always, TestRun
1374       [["mkdir"; "/new"];
1375        ["mkdir_p"; "/new"]];
1376     InitBasicFS, Always, TestLastFail
1377       [["touch"; "/new"];
1378        ["mkdir_p"; "/new"]]],
1379    "create a directory and parents",
1380    "\
1381 Create a directory named C<path>, creating any parent directories
1382 as necessary.  This is like the C<mkdir -p> shell command.");
1383
1384   ("chmod", (RErr, [Int "mode"; Pathname "path"]), 34, [],
1385    [], (* XXX Need stat command to test *)
1386    "change file mode",
1387    "\
1388 Change the mode (permissions) of C<path> to C<mode>.  Only
1389 numeric modes are supported.
1390
1391 I<Note>: When using this command from guestfish, C<mode>
1392 by default would be decimal, unless you prefix it with
1393 C<0> to get octal, ie. use C<0700> not C<700>.
1394
1395 The mode actually set is affected by the umask.");
1396
1397   ("chown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 35, [],
1398    [], (* XXX Need stat command to test *)
1399    "change file owner and group",
1400    "\
1401 Change the file owner to C<owner> and group to C<group>.
1402
1403 Only numeric uid and gid are supported.  If you want to use
1404 names, you will need to locate and parse the password file
1405 yourself (Augeas support makes this relatively easy).");
1406
1407   ("exists", (RBool "existsflag", [Pathname "path"]), 36, [],
1408    [InitISOFS, Always, TestOutputTrue (
1409       [["exists"; "/empty"]]);
1410     InitISOFS, Always, TestOutputTrue (
1411       [["exists"; "/directory"]])],
1412    "test if file or directory exists",
1413    "\
1414 This returns C<true> if and only if there is a file, directory
1415 (or anything) with the given C<path> name.
1416
1417 See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>.");
1418
1419   ("is_file", (RBool "fileflag", [Pathname "path"]), 37, [],
1420    [InitISOFS, Always, TestOutputTrue (
1421       [["is_file"; "/known-1"]]);
1422     InitISOFS, Always, TestOutputFalse (
1423       [["is_file"; "/directory"]])],
1424    "test if file exists",
1425    "\
1426 This returns C<true> if and only if there is a file
1427 with the given C<path> name.  Note that it returns false for
1428 other objects like directories.
1429
1430 See also C<guestfs_stat>.");
1431
1432   ("is_dir", (RBool "dirflag", [Pathname "path"]), 38, [],
1433    [InitISOFS, Always, TestOutputFalse (
1434       [["is_dir"; "/known-3"]]);
1435     InitISOFS, Always, TestOutputTrue (
1436       [["is_dir"; "/directory"]])],
1437    "test if file exists",
1438    "\
1439 This returns C<true> if and only if there is a directory
1440 with the given C<path> name.  Note that it returns false for
1441 other objects like files.
1442
1443 See also C<guestfs_stat>.");
1444
1445   ("pvcreate", (RErr, [Device "device"]), 39, [Optional "lvm2"],
1446    [InitEmpty, Always, TestOutputListOfDevices (
1447       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1448        ["pvcreate"; "/dev/sda1"];
1449        ["pvcreate"; "/dev/sda2"];
1450        ["pvcreate"; "/dev/sda3"];
1451        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1452    "create an LVM physical volume",
1453    "\
1454 This creates an LVM physical volume on the named C<device>,
1455 where C<device> should usually be a partition name such
1456 as C</dev/sda1>.");
1457
1458   ("vgcreate", (RErr, [String "volgroup"; DeviceList "physvols"]), 40, [Optional "lvm2"],
1459    [InitEmpty, Always, TestOutputList (
1460       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1461        ["pvcreate"; "/dev/sda1"];
1462        ["pvcreate"; "/dev/sda2"];
1463        ["pvcreate"; "/dev/sda3"];
1464        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1465        ["vgcreate"; "VG2"; "/dev/sda3"];
1466        ["vgs"]], ["VG1"; "VG2"])],
1467    "create an LVM volume group",
1468    "\
1469 This creates an LVM volume group called C<volgroup>
1470 from the non-empty list of physical volumes C<physvols>.");
1471
1472   ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [Optional "lvm2"],
1473    [InitEmpty, Always, TestOutputList (
1474       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1475        ["pvcreate"; "/dev/sda1"];
1476        ["pvcreate"; "/dev/sda2"];
1477        ["pvcreate"; "/dev/sda3"];
1478        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1479        ["vgcreate"; "VG2"; "/dev/sda3"];
1480        ["lvcreate"; "LV1"; "VG1"; "50"];
1481        ["lvcreate"; "LV2"; "VG1"; "50"];
1482        ["lvcreate"; "LV3"; "VG2"; "50"];
1483        ["lvcreate"; "LV4"; "VG2"; "50"];
1484        ["lvcreate"; "LV5"; "VG2"; "50"];
1485        ["lvs"]],
1486       ["/dev/VG1/LV1"; "/dev/VG1/LV2";
1487        "/dev/VG2/LV3"; "/dev/VG2/LV4"; "/dev/VG2/LV5"])],
1488    "create an LVM logical volume",
1489    "\
1490 This creates an LVM logical volume called C<logvol>
1491 on the volume group C<volgroup>, with C<size> megabytes.");
1492
1493   ("mkfs", (RErr, [String "fstype"; Device "device"]), 42, [],
1494    [InitEmpty, Always, TestOutput (
1495       [["part_disk"; "/dev/sda"; "mbr"];
1496        ["mkfs"; "ext2"; "/dev/sda1"];
1497        ["mount_options"; ""; "/dev/sda1"; "/"];
1498        ["write_file"; "/new"; "new file contents"; "0"];
1499        ["cat"; "/new"]], "new file contents")],
1500    "make a filesystem",
1501    "\
1502 This creates a filesystem on C<device> (usually a partition
1503 or LVM logical volume).  The filesystem type is C<fstype>, for
1504 example C<ext3>.");
1505
1506   ("sfdisk", (RErr, [Device "device";
1507                      Int "cyls"; Int "heads"; Int "sectors";
1508                      StringList "lines"]), 43, [DangerWillRobinson],
1509    [],
1510    "create partitions on a block device",
1511    "\
1512 This is a direct interface to the L<sfdisk(8)> program for creating
1513 partitions on block devices.
1514
1515 C<device> should be a block device, for example C</dev/sda>.
1516
1517 C<cyls>, C<heads> and C<sectors> are the number of cylinders, heads
1518 and sectors on the device, which are passed directly to sfdisk as
1519 the I<-C>, I<-H> and I<-S> parameters.  If you pass C<0> for any
1520 of these, then the corresponding parameter is omitted.  Usually for
1521 'large' disks, you can just pass C<0> for these, but for small
1522 (floppy-sized) disks, sfdisk (or rather, the kernel) cannot work
1523 out the right geometry and you will need to tell it.
1524
1525 C<lines> is a list of lines that we feed to C<sfdisk>.  For more
1526 information refer to the L<sfdisk(8)> manpage.
1527
1528 To create a single partition occupying the whole disk, you would
1529 pass C<lines> as a single element list, when the single element being
1530 the string C<,> (comma).
1531
1532 See also: C<guestfs_sfdisk_l>, C<guestfs_sfdisk_N>,
1533 C<guestfs_part_init>");
1534
1535   ("write_file", (RErr, [Pathname "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning],
1536    [InitBasicFS, Always, TestOutput (
1537       [["write_file"; "/new"; "new file contents"; "0"];
1538        ["cat"; "/new"]], "new file contents");
1539     InitBasicFS, Always, TestOutput (
1540       [["write_file"; "/new"; "\nnew file contents\n"; "0"];
1541        ["cat"; "/new"]], "\nnew file contents\n");
1542     InitBasicFS, Always, TestOutput (
1543       [["write_file"; "/new"; "\n\n"; "0"];
1544        ["cat"; "/new"]], "\n\n");
1545     InitBasicFS, Always, TestOutput (
1546       [["write_file"; "/new"; ""; "0"];
1547        ["cat"; "/new"]], "");
1548     InitBasicFS, Always, TestOutput (
1549       [["write_file"; "/new"; "\n\n\n"; "0"];
1550        ["cat"; "/new"]], "\n\n\n");
1551     InitBasicFS, Always, TestOutput (
1552       [["write_file"; "/new"; "\n"; "0"];
1553        ["cat"; "/new"]], "\n")],
1554    "create a file",
1555    "\
1556 This call creates a file called C<path>.  The contents of the
1557 file is the string C<content> (which can contain any 8 bit data),
1558 with length C<size>.
1559
1560 As a special case, if C<size> is C<0>
1561 then the length is calculated using C<strlen> (so in this case
1562 the content cannot contain embedded ASCII NULs).
1563
1564 I<NB.> Owing to a bug, writing content containing ASCII NUL
1565 characters does I<not> work, even if the length is specified.
1566 We hope to resolve this bug in a future version.  In the meantime
1567 use C<guestfs_upload>.");
1568
1569   ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"],
1570    [InitEmpty, Always, TestOutputListOfDevices (
1571       [["part_disk"; "/dev/sda"; "mbr"];
1572        ["mkfs"; "ext2"; "/dev/sda1"];
1573        ["mount_options"; ""; "/dev/sda1"; "/"];
1574        ["mounts"]], ["/dev/sda1"]);
1575     InitEmpty, Always, TestOutputList (
1576       [["part_disk"; "/dev/sda"; "mbr"];
1577        ["mkfs"; "ext2"; "/dev/sda1"];
1578        ["mount_options"; ""; "/dev/sda1"; "/"];
1579        ["umount"; "/"];
1580        ["mounts"]], [])],
1581    "unmount a filesystem",
1582    "\
1583 This unmounts the given filesystem.  The filesystem may be
1584 specified either by its mountpoint (path) or the device which
1585 contains the filesystem.");
1586
1587   ("mounts", (RStringList "devices", []), 46, [],
1588    [InitBasicFS, Always, TestOutputListOfDevices (
1589       [["mounts"]], ["/dev/sda1"])],
1590    "show mounted filesystems",
1591    "\
1592 This returns the list of currently mounted filesystems.  It returns
1593 the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
1594
1595 Some internal mounts are not shown.
1596
1597 See also: C<guestfs_mountpoints>");
1598
1599   ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"],
1600    [InitBasicFS, Always, TestOutputList (
1601       [["umount_all"];
1602        ["mounts"]], []);
1603     (* check that umount_all can unmount nested mounts correctly: *)
1604     InitEmpty, Always, TestOutputList (
1605       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1606        ["mkfs"; "ext2"; "/dev/sda1"];
1607        ["mkfs"; "ext2"; "/dev/sda2"];
1608        ["mkfs"; "ext2"; "/dev/sda3"];
1609        ["mount_options"; ""; "/dev/sda1"; "/"];
1610        ["mkdir"; "/mp1"];
1611        ["mount_options"; ""; "/dev/sda2"; "/mp1"];
1612        ["mkdir"; "/mp1/mp2"];
1613        ["mount_options"; ""; "/dev/sda3"; "/mp1/mp2"];
1614        ["mkdir"; "/mp1/mp2/mp3"];
1615        ["umount_all"];
1616        ["mounts"]], [])],
1617    "unmount all filesystems",
1618    "\
1619 This unmounts all mounted filesystems.
1620
1621 Some internal mounts are not unmounted by this call.");
1622
1623   ("lvm_remove_all", (RErr, []), 48, [DangerWillRobinson; Optional "lvm2"],
1624    [],
1625    "remove all LVM LVs, VGs and PVs",
1626    "\
1627 This command removes all LVM logical volumes, volume groups
1628 and physical volumes.");
1629
1630   ("file", (RString "description", [Dev_or_Path "path"]), 49, [],
1631    [InitISOFS, Always, TestOutput (
1632       [["file"; "/empty"]], "empty");
1633     InitISOFS, Always, TestOutput (
1634       [["file"; "/known-1"]], "ASCII text");
1635     InitISOFS, Always, TestLastFail (
1636       [["file"; "/notexists"]])],
1637    "determine file type",
1638    "\
1639 This call uses the standard L<file(1)> command to determine
1640 the type or contents of the file.  This also works on devices,
1641 for example to find out whether a partition contains a filesystem.
1642
1643 This call will also transparently look inside various types
1644 of compressed file.
1645
1646 The exact command which runs is C<file -zbsL path>.  Note in
1647 particular that the filename is not prepended to the output
1648 (the C<-b> option).");
1649
1650   ("command", (RString "output", [StringList "arguments"]), 50, [ProtocolLimitWarning],
1651    [InitBasicFS, Always, TestOutput (
1652       [["upload"; "test-command"; "/test-command"];
1653        ["chmod"; "0o755"; "/test-command"];
1654        ["command"; "/test-command 1"]], "Result1");
1655     InitBasicFS, Always, TestOutput (
1656       [["upload"; "test-command"; "/test-command"];
1657        ["chmod"; "0o755"; "/test-command"];
1658        ["command"; "/test-command 2"]], "Result2\n");
1659     InitBasicFS, Always, TestOutput (
1660       [["upload"; "test-command"; "/test-command"];
1661        ["chmod"; "0o755"; "/test-command"];
1662        ["command"; "/test-command 3"]], "\nResult3");
1663     InitBasicFS, Always, TestOutput (
1664       [["upload"; "test-command"; "/test-command"];
1665        ["chmod"; "0o755"; "/test-command"];
1666        ["command"; "/test-command 4"]], "\nResult4\n");
1667     InitBasicFS, Always, TestOutput (
1668       [["upload"; "test-command"; "/test-command"];
1669        ["chmod"; "0o755"; "/test-command"];
1670        ["command"; "/test-command 5"]], "\nResult5\n\n");
1671     InitBasicFS, Always, TestOutput (
1672       [["upload"; "test-command"; "/test-command"];
1673        ["chmod"; "0o755"; "/test-command"];
1674        ["command"; "/test-command 6"]], "\n\nResult6\n\n");
1675     InitBasicFS, Always, TestOutput (
1676       [["upload"; "test-command"; "/test-command"];
1677        ["chmod"; "0o755"; "/test-command"];
1678        ["command"; "/test-command 7"]], "");
1679     InitBasicFS, Always, TestOutput (
1680       [["upload"; "test-command"; "/test-command"];
1681        ["chmod"; "0o755"; "/test-command"];
1682        ["command"; "/test-command 8"]], "\n");
1683     InitBasicFS, Always, TestOutput (
1684       [["upload"; "test-command"; "/test-command"];
1685        ["chmod"; "0o755"; "/test-command"];
1686        ["command"; "/test-command 9"]], "\n\n");
1687     InitBasicFS, Always, TestOutput (
1688       [["upload"; "test-command"; "/test-command"];
1689        ["chmod"; "0o755"; "/test-command"];
1690        ["command"; "/test-command 10"]], "Result10-1\nResult10-2\n");
1691     InitBasicFS, Always, TestOutput (
1692       [["upload"; "test-command"; "/test-command"];
1693        ["chmod"; "0o755"; "/test-command"];
1694        ["command"; "/test-command 11"]], "Result11-1\nResult11-2");
1695     InitBasicFS, Always, TestLastFail (
1696       [["upload"; "test-command"; "/test-command"];
1697        ["chmod"; "0o755"; "/test-command"];
1698        ["command"; "/test-command"]])],
1699    "run a command from the guest filesystem",
1700    "\
1701 This call runs a command from the guest filesystem.  The
1702 filesystem must be mounted, and must contain a compatible
1703 operating system (ie. something Linux, with the same
1704 or compatible processor architecture).
1705
1706 The single parameter is an argv-style list of arguments.
1707 The first element is the name of the program to run.
1708 Subsequent elements are parameters.  The list must be
1709 non-empty (ie. must contain a program name).  Note that
1710 the command runs directly, and is I<not> invoked via
1711 the shell (see C<guestfs_sh>).
1712
1713 The return value is anything printed to I<stdout> by
1714 the command.
1715
1716 If the command returns a non-zero exit status, then
1717 this function returns an error message.  The error message
1718 string is the content of I<stderr> from the command.
1719
1720 The C<$PATH> environment variable will contain at least
1721 C</usr/bin> and C</bin>.  If you require a program from
1722 another location, you should provide the full path in the
1723 first parameter.
1724
1725 Shared libraries and data files required by the program
1726 must be available on filesystems which are mounted in the
1727 correct places.  It is the caller's responsibility to ensure
1728 all filesystems that are needed are mounted at the right
1729 locations.");
1730
1731   ("command_lines", (RStringList "lines", [StringList "arguments"]), 51, [ProtocolLimitWarning],
1732    [InitBasicFS, Always, TestOutputList (
1733       [["upload"; "test-command"; "/test-command"];
1734        ["chmod"; "0o755"; "/test-command"];
1735        ["command_lines"; "/test-command 1"]], ["Result1"]);
1736     InitBasicFS, Always, TestOutputList (
1737       [["upload"; "test-command"; "/test-command"];
1738        ["chmod"; "0o755"; "/test-command"];
1739        ["command_lines"; "/test-command 2"]], ["Result2"]);
1740     InitBasicFS, Always, TestOutputList (
1741       [["upload"; "test-command"; "/test-command"];
1742        ["chmod"; "0o755"; "/test-command"];
1743        ["command_lines"; "/test-command 3"]], ["";"Result3"]);
1744     InitBasicFS, Always, TestOutputList (
1745       [["upload"; "test-command"; "/test-command"];
1746        ["chmod"; "0o755"; "/test-command"];
1747        ["command_lines"; "/test-command 4"]], ["";"Result4"]);
1748     InitBasicFS, Always, TestOutputList (
1749       [["upload"; "test-command"; "/test-command"];
1750        ["chmod"; "0o755"; "/test-command"];
1751        ["command_lines"; "/test-command 5"]], ["";"Result5";""]);
1752     InitBasicFS, Always, TestOutputList (
1753       [["upload"; "test-command"; "/test-command"];
1754        ["chmod"; "0o755"; "/test-command"];
1755        ["command_lines"; "/test-command 6"]], ["";"";"Result6";""]);
1756     InitBasicFS, Always, TestOutputList (
1757       [["upload"; "test-command"; "/test-command"];
1758        ["chmod"; "0o755"; "/test-command"];
1759        ["command_lines"; "/test-command 7"]], []);
1760     InitBasicFS, Always, TestOutputList (
1761       [["upload"; "test-command"; "/test-command"];
1762        ["chmod"; "0o755"; "/test-command"];
1763        ["command_lines"; "/test-command 8"]], [""]);
1764     InitBasicFS, Always, TestOutputList (
1765       [["upload"; "test-command"; "/test-command"];
1766        ["chmod"; "0o755"; "/test-command"];
1767        ["command_lines"; "/test-command 9"]], ["";""]);
1768     InitBasicFS, Always, TestOutputList (
1769       [["upload"; "test-command"; "/test-command"];
1770        ["chmod"; "0o755"; "/test-command"];
1771        ["command_lines"; "/test-command 10"]], ["Result10-1";"Result10-2"]);
1772     InitBasicFS, Always, TestOutputList (
1773       [["upload"; "test-command"; "/test-command"];
1774        ["chmod"; "0o755"; "/test-command"];
1775        ["command_lines"; "/test-command 11"]], ["Result11-1";"Result11-2"])],
1776    "run a command, returning lines",
1777    "\
1778 This is the same as C<guestfs_command>, but splits the
1779 result into a list of lines.
1780
1781 See also: C<guestfs_sh_lines>");
1782
1783   ("stat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 52, [],
1784    [InitISOFS, Always, TestOutputStruct (
1785       [["stat"; "/empty"]], [CompareWithInt ("size", 0)])],
1786    "get file information",
1787    "\
1788 Returns file information for the given C<path>.
1789
1790 This is the same as the C<stat(2)> system call.");
1791
1792   ("lstat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 53, [],
1793    [InitISOFS, Always, TestOutputStruct (
1794       [["lstat"; "/empty"]], [CompareWithInt ("size", 0)])],
1795    "get file information for a symbolic link",
1796    "\
1797 Returns file information for the given C<path>.
1798
1799 This is the same as C<guestfs_stat> except that if C<path>
1800 is a symbolic link, then the link is stat-ed, not the file it
1801 refers to.
1802
1803 This is the same as the C<lstat(2)> system call.");
1804
1805   ("statvfs", (RStruct ("statbuf", "statvfs"), [Pathname "path"]), 54, [],
1806    [InitISOFS, Always, TestOutputStruct (
1807       [["statvfs"; "/"]], [CompareWithInt ("namemax", 255)])],
1808    "get file system statistics",
1809    "\
1810 Returns file system statistics for any mounted file system.
1811 C<path> should be a file or directory in the mounted file system
1812 (typically it is the mount point itself, but it doesn't need to be).
1813
1814 This is the same as the C<statvfs(2)> system call.");
1815
1816   ("tune2fs_l", (RHashtable "superblock", [Device "device"]), 55, [],
1817    [], (* XXX test *)
1818    "get ext2/ext3/ext4 superblock details",
1819    "\
1820 This returns the contents of the ext2, ext3 or ext4 filesystem
1821 superblock on C<device>.
1822
1823 It is the same as running C<tune2fs -l device>.  See L<tune2fs(8)>
1824 manpage for more details.  The list of fields returned isn't
1825 clearly defined, and depends on both the version of C<tune2fs>
1826 that libguestfs was built against, and the filesystem itself.");
1827
1828   ("blockdev_setro", (RErr, [Device "device"]), 56, [],
1829    [InitEmpty, Always, TestOutputTrue (
1830       [["blockdev_setro"; "/dev/sda"];
1831        ["blockdev_getro"; "/dev/sda"]])],
1832    "set block device to read-only",
1833    "\
1834 Sets the block device named C<device> to read-only.
1835
1836 This uses the L<blockdev(8)> command.");
1837
1838   ("blockdev_setrw", (RErr, [Device "device"]), 57, [],
1839    [InitEmpty, Always, TestOutputFalse (
1840       [["blockdev_setrw"; "/dev/sda"];
1841        ["blockdev_getro"; "/dev/sda"]])],
1842    "set block device to read-write",
1843    "\
1844 Sets the block device named C<device> to read-write.
1845
1846 This uses the L<blockdev(8)> command.");
1847
1848   ("blockdev_getro", (RBool "ro", [Device "device"]), 58, [],
1849    [InitEmpty, Always, TestOutputTrue (
1850       [["blockdev_setro"; "/dev/sda"];
1851        ["blockdev_getro"; "/dev/sda"]])],
1852    "is block device set to read-only",
1853    "\
1854 Returns a boolean indicating if the block device is read-only
1855 (true if read-only, false if not).
1856
1857 This uses the L<blockdev(8)> command.");
1858
1859   ("blockdev_getss", (RInt "sectorsize", [Device "device"]), 59, [],
1860    [InitEmpty, Always, TestOutputInt (
1861       [["blockdev_getss"; "/dev/sda"]], 512)],
1862    "get sectorsize of block device",
1863    "\
1864 This returns the size of sectors on a block device.
1865 Usually 512, but can be larger for modern devices.
1866
1867 (Note, this is not the size in sectors, use C<guestfs_blockdev_getsz>
1868 for that).
1869
1870 This uses the L<blockdev(8)> command.");
1871
1872   ("blockdev_getbsz", (RInt "blocksize", [Device "device"]), 60, [],
1873    [InitEmpty, Always, TestOutputInt (
1874       [["blockdev_getbsz"; "/dev/sda"]], 4096)],
1875    "get blocksize of block device",
1876    "\
1877 This returns the block size of a device.
1878
1879 (Note this is different from both I<size in blocks> and
1880 I<filesystem block size>).
1881
1882 This uses the L<blockdev(8)> command.");
1883
1884   ("blockdev_setbsz", (RErr, [Device "device"; Int "blocksize"]), 61, [],
1885    [], (* XXX test *)
1886    "set blocksize of block device",
1887    "\
1888 This sets the block size of a device.
1889
1890 (Note this is different from both I<size in blocks> and
1891 I<filesystem block size>).
1892
1893 This uses the L<blockdev(8)> command.");
1894
1895   ("blockdev_getsz", (RInt64 "sizeinsectors", [Device "device"]), 62, [],
1896    [InitEmpty, Always, TestOutputInt (
1897       [["blockdev_getsz"; "/dev/sda"]], 1024000)],
1898    "get total size of device in 512-byte sectors",
1899    "\
1900 This returns the size of the device in units of 512-byte sectors
1901 (even if the sectorsize isn't 512 bytes ... weird).
1902
1903 See also C<guestfs_blockdev_getss> for the real sector size of
1904 the device, and C<guestfs_blockdev_getsize64> for the more
1905 useful I<size in bytes>.
1906
1907 This uses the L<blockdev(8)> command.");
1908
1909   ("blockdev_getsize64", (RInt64 "sizeinbytes", [Device "device"]), 63, [],
1910    [InitEmpty, Always, TestOutputInt (
1911       [["blockdev_getsize64"; "/dev/sda"]], 524288000)],
1912    "get total size of device in bytes",
1913    "\
1914 This returns the size of the device in bytes.
1915
1916 See also C<guestfs_blockdev_getsz>.
1917
1918 This uses the L<blockdev(8)> command.");
1919
1920   ("blockdev_flushbufs", (RErr, [Device "device"]), 64, [],
1921    [InitEmpty, Always, TestRun
1922       [["blockdev_flushbufs"; "/dev/sda"]]],
1923    "flush device buffers",
1924    "\
1925 This tells the kernel to flush internal buffers associated
1926 with C<device>.
1927
1928 This uses the L<blockdev(8)> command.");
1929
1930   ("blockdev_rereadpt", (RErr, [Device "device"]), 65, [],
1931    [InitEmpty, Always, TestRun
1932       [["blockdev_rereadpt"; "/dev/sda"]]],
1933    "reread partition table",
1934    "\
1935 Reread the partition table on C<device>.
1936
1937 This uses the L<blockdev(8)> command.");
1938
1939   ("upload", (RErr, [FileIn "filename"; Dev_or_Path "remotefilename"]), 66, [],
1940    [InitBasicFS, Always, TestOutput (
1941       (* Pick a file from cwd which isn't likely to change. *)
1942       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1943        ["checksum"; "md5"; "/COPYING.LIB"]],
1944       Digest.to_hex (Digest.file "COPYING.LIB"))],
1945    "upload a file from the local machine",
1946    "\
1947 Upload local file C<filename> to C<remotefilename> on the
1948 filesystem.
1949
1950 C<filename> can also be a named pipe.
1951
1952 See also C<guestfs_download>.");
1953
1954   ("download", (RErr, [Dev_or_Path "remotefilename"; FileOut "filename"]), 67, [],
1955    [InitBasicFS, Always, TestOutput (
1956       (* Pick a file from cwd which isn't likely to change. *)
1957       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1958        ["download"; "/COPYING.LIB"; "testdownload.tmp"];
1959        ["upload"; "testdownload.tmp"; "/upload"];
1960        ["checksum"; "md5"; "/upload"]],
1961       Digest.to_hex (Digest.file "COPYING.LIB"))],
1962    "download a file to the local machine",
1963    "\
1964 Download file C<remotefilename> and save it as C<filename>
1965 on the local machine.
1966
1967 C<filename> can also be a named pipe.
1968
1969 See also C<guestfs_upload>, C<guestfs_cat>.");
1970
1971   ("checksum", (RString "checksum", [String "csumtype"; Pathname "path"]), 68, [],
1972    [InitISOFS, Always, TestOutput (
1973       [["checksum"; "crc"; "/known-3"]], "2891671662");
1974     InitISOFS, Always, TestLastFail (
1975       [["checksum"; "crc"; "/notexists"]]);
1976     InitISOFS, Always, TestOutput (
1977       [["checksum"; "md5"; "/known-3"]], "46d6ca27ee07cdc6fa99c2e138cc522c");
1978     InitISOFS, Always, TestOutput (
1979       [["checksum"; "sha1"; "/known-3"]], "b7ebccc3ee418311091c3eda0a45b83c0a770f15");
1980     InitISOFS, Always, TestOutput (
1981       [["checksum"; "sha224"; "/known-3"]], "d2cd1774b28f3659c14116be0a6dc2bb5c4b350ce9cd5defac707741");
1982     InitISOFS, Always, TestOutput (
1983       [["checksum"; "sha256"; "/known-3"]], "75bb71b90cd20cb13f86d2bea8dad63ac7194e7517c3b52b8d06ff52d3487d30");
1984     InitISOFS, Always, TestOutput (
1985       [["checksum"; "sha384"; "/known-3"]], "5fa7883430f357b5d7b7271d3a1d2872b51d73cba72731de6863d3dea55f30646af2799bef44d5ea776a5ec7941ac640");
1986     InitISOFS, Always, TestOutput (
1987       [["checksum"; "sha512"; "/known-3"]], "2794062c328c6b216dca90443b7f7134c5f40e56bd0ed7853123275a09982a6f992e6ca682f9d2fba34a4c5e870d8fe077694ff831e3032a004ee077e00603f6")],
1988    "compute MD5, SHAx or CRC checksum of file",
1989    "\
1990 This call computes the MD5, SHAx or CRC checksum of the
1991 file named C<path>.
1992
1993 The type of checksum to compute is given by the C<csumtype>
1994 parameter which must have one of the following values:
1995
1996 =over 4
1997
1998 =item C<crc>
1999
2000 Compute the cyclic redundancy check (CRC) specified by POSIX
2001 for the C<cksum> command.
2002
2003 =item C<md5>
2004
2005 Compute the MD5 hash (using the C<md5sum> program).
2006
2007 =item C<sha1>
2008
2009 Compute the SHA1 hash (using the C<sha1sum> program).
2010
2011 =item C<sha224>
2012
2013 Compute the SHA224 hash (using the C<sha224sum> program).
2014
2015 =item C<sha256>
2016
2017 Compute the SHA256 hash (using the C<sha256sum> program).
2018
2019 =item C<sha384>
2020
2021 Compute the SHA384 hash (using the C<sha384sum> program).
2022
2023 =item C<sha512>
2024
2025 Compute the SHA512 hash (using the C<sha512sum> program).
2026
2027 =back
2028
2029 The checksum is returned as a printable string.
2030
2031 To get the checksum for a device, use C<guestfs_checksum_device>.");
2032
2033   ("tar_in", (RErr, [FileIn "tarfile"; Pathname "directory"]), 69, [],
2034    [InitBasicFS, Always, TestOutput (
2035       [["tar_in"; "../images/helloworld.tar"; "/"];
2036        ["cat"; "/hello"]], "hello\n")],
2037    "unpack tarfile to directory",
2038    "\
2039 This command uploads and unpacks local file C<tarfile> (an
2040 I<uncompressed> tar file) into C<directory>.
2041
2042 To upload a compressed tarball, use C<guestfs_tgz_in>
2043 or C<guestfs_txz_in>.");
2044
2045   ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [],
2046    [],
2047    "pack directory into tarfile",
2048    "\
2049 This command packs the contents of C<directory> and downloads
2050 it to local file C<tarfile>.
2051
2052 To download a compressed tarball, use C<guestfs_tgz_out>
2053 or C<guestfs_txz_out>.");
2054
2055   ("tgz_in", (RErr, [FileIn "tarball"; Pathname "directory"]), 71, [],
2056    [InitBasicFS, Always, TestOutput (
2057       [["tgz_in"; "../images/helloworld.tar.gz"; "/"];
2058        ["cat"; "/hello"]], "hello\n")],
2059    "unpack compressed tarball to directory",
2060    "\
2061 This command uploads and unpacks local file C<tarball> (a
2062 I<gzip compressed> tar file) into C<directory>.
2063
2064 To upload an uncompressed tarball, use C<guestfs_tar_in>.");
2065
2066   ("tgz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 72, [],
2067    [],
2068    "pack directory into compressed tarball",
2069    "\
2070 This command packs the contents of C<directory> and downloads
2071 it to local file C<tarball>.
2072
2073 To download an uncompressed tarball, use C<guestfs_tar_out>.");
2074
2075   ("mount_ro", (RErr, [Device "device"; String "mountpoint"]), 73, [],
2076    [InitBasicFS, Always, TestLastFail (
2077       [["umount"; "/"];
2078        ["mount_ro"; "/dev/sda1"; "/"];
2079        ["touch"; "/new"]]);
2080     InitBasicFS, Always, TestOutput (
2081       [["write_file"; "/new"; "data"; "0"];
2082        ["umount"; "/"];
2083        ["mount_ro"; "/dev/sda1"; "/"];
2084        ["cat"; "/new"]], "data")],
2085    "mount a guest disk, read-only",
2086    "\
2087 This is the same as the C<guestfs_mount> command, but it
2088 mounts the filesystem with the read-only (I<-o ro>) flag.");
2089
2090   ("mount_options", (RErr, [String "options"; Device "device"; String "mountpoint"]), 74, [],
2091    [],
2092    "mount a guest disk with mount options",
2093    "\
2094 This is the same as the C<guestfs_mount> command, but it
2095 allows you to set the mount options as for the
2096 L<mount(8)> I<-o> flag.");
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_file"; "/old"; "file content"; "0"];
2330        ["cp"; "/old"; "/new"];
2331        ["cat"; "/new"]], "file content");
2332     InitBasicFS, Always, TestOutputTrue (
2333       [["write_file"; "/old"; "file content"; "0"];
2334        ["cp"; "/old"; "/new"];
2335        ["is_file"; "/old"]]);
2336     InitBasicFS, Always, TestOutput (
2337       [["write_file"; "/old"; "file content"; "0"];
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_file"; "/olddir/file"; "file content"; "0"];
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_file"; "/old"; "file content"; "0"];
2361        ["mv"; "/old"; "/new"];
2362        ["cat"; "/new"]], "file content");
2363     InitBasicFS, Always, TestOutputFalse (
2364       [["write_file"; "/old"; "file content"; "0"];
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_file"; "/file1"; "contents of a file"; "0"];
2414        ["cp"; "/file1"; "/file2"];
2415        ["equal"; "/file1"; "/file2"]]);
2416     InitBasicFS, Always, TestOutputFalse (
2417       [["write_file"; "/file1"; "contents of a file"; "0"];
2418        ["write_file"; "/file2"; "contents of another file"; "0"];
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    "print the printable strings in a file",
2435    "\
2436 This runs the L<strings(1)> command on a file and returns
2437 the list of printable strings found.");
2438
2439   ("strings_e", (RStringList "stringsout", [String "encoding"; Pathname "path"]), 95, [ProtocolLimitWarning],
2440    [InitISOFS, Always, TestOutputList (
2441       [["strings_e"; "b"; "/known-5"]], []);
2442     InitBasicFS, Disabled, TestOutputList (
2443       [["write_file"; "/new"; "\000h\000e\000l\000l\000o\000\n\000w\000o\000r\000l\000d\000\n"; "24"];
2444        ["strings_e"; "b"; "/new"]], ["hello"; "world"])],
2445    "print the printable strings in a file",
2446    "\
2447 This is like the C<guestfs_strings> command, but allows you to
2448 specify the encoding.
2449
2450 See the L<strings(1)> manpage for the full list of encodings.
2451
2452 Commonly useful encodings are C<l> (lower case L) which will
2453 show strings inside Windows/x86 files.
2454
2455 The returned strings are transcoded to UTF-8.");
2456
2457   ("hexdump", (RString "dump", [Pathname "path"]), 96, [ProtocolLimitWarning],
2458    [InitISOFS, Always, TestOutput (
2459       [["hexdump"; "/known-4"]], "00000000  61 62 63 0a 64 65 66 0a  67 68 69                 |abc.def.ghi|\n0000000b\n");
2460     (* Test for RHBZ#501888c2 regression which caused large hexdump
2461      * commands to segfault.
2462      *)
2463     InitISOFS, Always, TestRun (
2464       [["hexdump"; "/100krandom"]])],
2465    "dump a file in hexadecimal",
2466    "\
2467 This runs C<hexdump -C> on the given C<path>.  The result is
2468 the human-readable, canonical hex dump of the file.");
2469
2470   ("zerofree", (RErr, [Device "device"]), 97, [Optional "zerofree"],
2471    [InitNone, Always, TestOutput (
2472       [["part_disk"; "/dev/sda"; "mbr"];
2473        ["mkfs"; "ext3"; "/dev/sda1"];
2474        ["mount_options"; ""; "/dev/sda1"; "/"];
2475        ["write_file"; "/new"; "test file"; "0"];
2476        ["umount"; "/dev/sda1"];
2477        ["zerofree"; "/dev/sda1"];
2478        ["mount_options"; ""; "/dev/sda1"; "/"];
2479        ["cat"; "/new"]], "test file")],
2480    "zero unused inodes and disk blocks on ext2/3 filesystem",
2481    "\
2482 This runs the I<zerofree> program on C<device>.  This program
2483 claims to zero unused inodes and disk blocks on an ext2/3
2484 filesystem, thus making it possible to compress the filesystem
2485 more effectively.
2486
2487 You should B<not> run this program if the filesystem is
2488 mounted.
2489
2490 It is possible that using this program can damage the filesystem
2491 or data on the filesystem.");
2492
2493   ("pvresize", (RErr, [Device "device"]), 98, [Optional "lvm2"],
2494    [],
2495    "resize an LVM physical volume",
2496    "\
2497 This resizes (expands or shrinks) an existing LVM physical
2498 volume to match the new size of the underlying device.");
2499
2500   ("sfdisk_N", (RErr, [Device "device"; Int "partnum";
2501                        Int "cyls"; Int "heads"; Int "sectors";
2502                        String "line"]), 99, [DangerWillRobinson],
2503    [],
2504    "modify a single partition on a block device",
2505    "\
2506 This runs L<sfdisk(8)> option to modify just the single
2507 partition C<n> (note: C<n> counts from 1).
2508
2509 For other parameters, see C<guestfs_sfdisk>.  You should usually
2510 pass C<0> for the cyls/heads/sectors parameters.
2511
2512 See also: C<guestfs_part_add>");
2513
2514   ("sfdisk_l", (RString "partitions", [Device "device"]), 100, [],
2515    [],
2516    "display the partition table",
2517    "\
2518 This displays the partition table on C<device>, in the
2519 human-readable output of the L<sfdisk(8)> command.  It is
2520 not intended to be parsed.
2521
2522 See also: C<guestfs_part_list>");
2523
2524   ("sfdisk_kernel_geometry", (RString "partitions", [Device "device"]), 101, [],
2525    [],
2526    "display the kernel geometry",
2527    "\
2528 This displays the kernel's idea of the geometry of C<device>.
2529
2530 The result is in human-readable format, and not designed to
2531 be parsed.");
2532
2533   ("sfdisk_disk_geometry", (RString "partitions", [Device "device"]), 102, [],
2534    [],
2535    "display the disk geometry from the partition table",
2536    "\
2537 This displays the disk geometry of C<device> read from the
2538 partition table.  Especially in the case where the underlying
2539 block device has been resized, this can be different from the
2540 kernel's idea of the geometry (see C<guestfs_sfdisk_kernel_geometry>).
2541
2542 The result is in human-readable format, and not designed to
2543 be parsed.");
2544
2545   ("vg_activate_all", (RErr, [Bool "activate"]), 103, [Optional "lvm2"],
2546    [],
2547    "activate or deactivate all volume groups",
2548    "\
2549 This command activates or (if C<activate> is false) deactivates
2550 all logical volumes in all volume groups.
2551 If activated, then they are made known to the
2552 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2553 then those devices disappear.
2554
2555 This command is the same as running C<vgchange -a y|n>");
2556
2557   ("vg_activate", (RErr, [Bool "activate"; StringList "volgroups"]), 104, [Optional "lvm2"],
2558    [],
2559    "activate or deactivate some volume groups",
2560    "\
2561 This command activates or (if C<activate> is false) deactivates
2562 all logical volumes in the listed volume groups C<volgroups>.
2563 If activated, then they are made known to the
2564 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2565 then those devices disappear.
2566
2567 This command is the same as running C<vgchange -a y|n volgroups...>
2568
2569 Note that if C<volgroups> is an empty list then B<all> volume groups
2570 are activated or deactivated.");
2571
2572   ("lvresize", (RErr, [Device "device"; Int "mbytes"]), 105, [Optional "lvm2"],
2573    [InitNone, Always, TestOutput (
2574       [["part_disk"; "/dev/sda"; "mbr"];
2575        ["pvcreate"; "/dev/sda1"];
2576        ["vgcreate"; "VG"; "/dev/sda1"];
2577        ["lvcreate"; "LV"; "VG"; "10"];
2578        ["mkfs"; "ext2"; "/dev/VG/LV"];
2579        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2580        ["write_file"; "/new"; "test content"; "0"];
2581        ["umount"; "/"];
2582        ["lvresize"; "/dev/VG/LV"; "20"];
2583        ["e2fsck_f"; "/dev/VG/LV"];
2584        ["resize2fs"; "/dev/VG/LV"];
2585        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2586        ["cat"; "/new"]], "test content")],
2587    "resize an LVM logical volume",
2588    "\
2589 This resizes (expands or shrinks) an existing LVM logical
2590 volume to C<mbytes>.  When reducing, data in the reduced part
2591 is lost.");
2592
2593   ("resize2fs", (RErr, [Device "device"]), 106, [],
2594    [], (* lvresize tests this *)
2595    "resize an ext2/ext3 filesystem",
2596    "\
2597 This resizes an ext2 or ext3 filesystem to match the size of
2598 the underlying device.
2599
2600 I<Note:> It is sometimes required that you run C<guestfs_e2fsck_f>
2601 on the C<device> before calling this command.  For unknown reasons
2602 C<resize2fs> sometimes gives an error about this and sometimes not.
2603 In any case, it is always safe to call C<guestfs_e2fsck_f> before
2604 calling this function.");
2605
2606   ("find", (RStringList "names", [Pathname "directory"]), 107, [ProtocolLimitWarning],
2607    [InitBasicFS, Always, TestOutputList (
2608       [["find"; "/"]], ["lost+found"]);
2609     InitBasicFS, Always, TestOutputList (
2610       [["touch"; "/a"];
2611        ["mkdir"; "/b"];
2612        ["touch"; "/b/c"];
2613        ["find"; "/"]], ["a"; "b"; "b/c"; "lost+found"]);
2614     InitBasicFS, Always, TestOutputList (
2615       [["mkdir_p"; "/a/b/c"];
2616        ["touch"; "/a/b/c/d"];
2617        ["find"; "/a/b/"]], ["c"; "c/d"])],
2618    "find all files and directories",
2619    "\
2620 This command lists out all files and directories, recursively,
2621 starting at C<directory>.  It is essentially equivalent to
2622 running the shell command C<find directory -print> but some
2623 post-processing happens on the output, described below.
2624
2625 This returns a list of strings I<without any prefix>.  Thus
2626 if the directory structure was:
2627
2628  /tmp/a
2629  /tmp/b
2630  /tmp/c/d
2631
2632 then the returned list from C<guestfs_find> C</tmp> would be
2633 4 elements:
2634
2635  a
2636  b
2637  c
2638  c/d
2639
2640 If C<directory> is not a directory, then this command returns
2641 an error.
2642
2643 The returned list is sorted.
2644
2645 See also C<guestfs_find0>.");
2646
2647   ("e2fsck_f", (RErr, [Device "device"]), 108, [],
2648    [], (* lvresize tests this *)
2649    "check an ext2/ext3 filesystem",
2650    "\
2651 This runs C<e2fsck -p -f device>, ie. runs the ext2/ext3
2652 filesystem checker on C<device>, noninteractively (C<-p>),
2653 even if the filesystem appears to be clean (C<-f>).
2654
2655 This command is only needed because of C<guestfs_resize2fs>
2656 (q.v.).  Normally you should use C<guestfs_fsck>.");
2657
2658   ("sleep", (RErr, [Int "secs"]), 109, [],
2659    [InitNone, Always, TestRun (
2660       [["sleep"; "1"]])],
2661    "sleep for some seconds",
2662    "\
2663 Sleep for C<secs> seconds.");
2664
2665   ("ntfs_3g_probe", (RInt "status", [Bool "rw"; Device "device"]), 110, [Optional "ntfs3g"],
2666    [InitNone, Always, TestOutputInt (
2667       [["part_disk"; "/dev/sda"; "mbr"];
2668        ["mkfs"; "ntfs"; "/dev/sda1"];
2669        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 0);
2670     InitNone, Always, TestOutputInt (
2671       [["part_disk"; "/dev/sda"; "mbr"];
2672        ["mkfs"; "ext2"; "/dev/sda1"];
2673        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 12)],
2674    "probe NTFS volume",
2675    "\
2676 This command runs the L<ntfs-3g.probe(8)> command which probes
2677 an NTFS C<device> for mountability.  (Not all NTFS volumes can
2678 be mounted read-write, and some cannot be mounted at all).
2679
2680 C<rw> is a boolean flag.  Set it to true if you want to test
2681 if the volume can be mounted read-write.  Set it to false if
2682 you want to test if the volume can be mounted read-only.
2683
2684 The return value is an integer which C<0> if the operation
2685 would succeed, or some non-zero value documented in the
2686 L<ntfs-3g.probe(8)> manual page.");
2687
2688   ("sh", (RString "output", [String "command"]), 111, [],
2689    [], (* XXX needs tests *)
2690    "run a command via the shell",
2691    "\
2692 This call runs a command from the guest filesystem via the
2693 guest's C</bin/sh>.
2694
2695 This is like C<guestfs_command>, but passes the command to:
2696
2697  /bin/sh -c \"command\"
2698
2699 Depending on the guest's shell, this usually results in
2700 wildcards being expanded, shell expressions being interpolated
2701 and so on.
2702
2703 All the provisos about C<guestfs_command> apply to this call.");
2704
2705   ("sh_lines", (RStringList "lines", [String "command"]), 112, [],
2706    [], (* XXX needs tests *)
2707    "run a command via the shell returning lines",
2708    "\
2709 This is the same as C<guestfs_sh>, but splits the result
2710 into a list of lines.
2711
2712 See also: C<guestfs_command_lines>");
2713
2714   ("glob_expand", (RStringList "paths", [Pathname "pattern"]), 113, [],
2715    (* Use Pathname here, and hence ABS_PATH (pattern,... in generated
2716     * code in stubs.c, since all valid glob patterns must start with "/".
2717     * There is no concept of "cwd" in libguestfs, hence no "."-relative names.
2718     *)
2719    [InitBasicFS, Always, TestOutputList (
2720       [["mkdir_p"; "/a/b/c"];
2721        ["touch"; "/a/b/c/d"];
2722        ["touch"; "/a/b/c/e"];
2723        ["glob_expand"; "/a/b/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2724     InitBasicFS, Always, TestOutputList (
2725       [["mkdir_p"; "/a/b/c"];
2726        ["touch"; "/a/b/c/d"];
2727        ["touch"; "/a/b/c/e"];
2728        ["glob_expand"; "/a/*/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2729     InitBasicFS, Always, TestOutputList (
2730       [["mkdir_p"; "/a/b/c"];
2731        ["touch"; "/a/b/c/d"];
2732        ["touch"; "/a/b/c/e"];
2733        ["glob_expand"; "/a/*/x/*"]], [])],
2734    "expand a wildcard path",
2735    "\
2736 This command searches for all the pathnames matching
2737 C<pattern> according to the wildcard expansion rules
2738 used by the shell.
2739
2740 If no paths match, then this returns an empty list
2741 (note: not an error).
2742
2743 It is just a wrapper around the C L<glob(3)> function
2744 with flags C<GLOB_MARK|GLOB_BRACE>.
2745 See that manual page for more details.");
2746
2747   ("scrub_device", (RErr, [Device "device"]), 114, [DangerWillRobinson; Optional "scrub"],
2748    [InitNone, Always, TestRun ( (* use /dev/sdc because it's smaller *)
2749       [["scrub_device"; "/dev/sdc"]])],
2750    "scrub (securely wipe) a device",
2751    "\
2752 This command writes patterns over C<device> to make data retrieval
2753 more difficult.
2754
2755 It is an interface to the L<scrub(1)> program.  See that
2756 manual page for more details.");
2757
2758   ("scrub_file", (RErr, [Pathname "file"]), 115, [Optional "scrub"],
2759    [InitBasicFS, Always, TestRun (
2760       [["write_file"; "/file"; "content"; "0"];
2761        ["scrub_file"; "/file"]])],
2762    "scrub (securely wipe) a file",
2763    "\
2764 This command writes patterns over a file to make data retrieval
2765 more difficult.
2766
2767 The file is I<removed> after scrubbing.
2768
2769 It is an interface to the L<scrub(1)> program.  See that
2770 manual page for more details.");
2771
2772   ("scrub_freespace", (RErr, [Pathname "dir"]), 116, [Optional "scrub"],
2773    [], (* XXX needs testing *)
2774    "scrub (securely wipe) free space",
2775    "\
2776 This command creates the directory C<dir> and then fills it
2777 with files until the filesystem is full, and scrubs the files
2778 as for C<guestfs_scrub_file>, and deletes them.
2779 The intention is to scrub any free space on the partition
2780 containing C<dir>.
2781
2782 It is an interface to the L<scrub(1)> program.  See that
2783 manual page for more details.");
2784
2785   ("mkdtemp", (RString "dir", [Pathname "template"]), 117, [],
2786    [InitBasicFS, Always, TestRun (
2787       [["mkdir"; "/tmp"];
2788        ["mkdtemp"; "/tmp/tmpXXXXXX"]])],
2789    "create a temporary directory",
2790    "\
2791 This command creates a temporary directory.  The
2792 C<template> parameter should be a full pathname for the
2793 temporary directory name with the final six characters being
2794 \"XXXXXX\".
2795
2796 For example: \"/tmp/myprogXXXXXX\" or \"/Temp/myprogXXXXXX\",
2797 the second one being suitable for Windows filesystems.
2798
2799 The name of the temporary directory that was created
2800 is returned.
2801
2802 The temporary directory is created with mode 0700
2803 and is owned by root.
2804
2805 The caller is responsible for deleting the temporary
2806 directory and its contents after use.
2807
2808 See also: L<mkdtemp(3)>");
2809
2810   ("wc_l", (RInt "lines", [Pathname "path"]), 118, [],
2811    [InitISOFS, Always, TestOutputInt (
2812       [["wc_l"; "/10klines"]], 10000)],
2813    "count lines in a file",
2814    "\
2815 This command counts the lines in a file, using the
2816 C<wc -l> external command.");
2817
2818   ("wc_w", (RInt "words", [Pathname "path"]), 119, [],
2819    [InitISOFS, Always, TestOutputInt (
2820       [["wc_w"; "/10klines"]], 10000)],
2821    "count words in a file",
2822    "\
2823 This command counts the words in a file, using the
2824 C<wc -w> external command.");
2825
2826   ("wc_c", (RInt "chars", [Pathname "path"]), 120, [],
2827    [InitISOFS, Always, TestOutputInt (
2828       [["wc_c"; "/100kallspaces"]], 102400)],
2829    "count characters in a file",
2830    "\
2831 This command counts the characters in a file, using the
2832 C<wc -c> external command.");
2833
2834   ("head", (RStringList "lines", [Pathname "path"]), 121, [ProtocolLimitWarning],
2835    [InitISOFS, Always, TestOutputList (
2836       [["head"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"])],
2837    "return first 10 lines of a file",
2838    "\
2839 This command returns up to the first 10 lines of a file as
2840 a list of strings.");
2841
2842   ("head_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 122, [ProtocolLimitWarning],
2843    [InitISOFS, Always, TestOutputList (
2844       [["head_n"; "3"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2845     InitISOFS, Always, TestOutputList (
2846       [["head_n"; "-9997"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2847     InitISOFS, Always, TestOutputList (
2848       [["head_n"; "0"; "/10klines"]], [])],
2849    "return first N lines of a file",
2850    "\
2851 If the parameter C<nrlines> is a positive number, this returns the first
2852 C<nrlines> lines of the file C<path>.
2853
2854 If the parameter C<nrlines> is a negative number, this returns lines
2855 from the file C<path>, excluding the last C<nrlines> lines.
2856
2857 If the parameter C<nrlines> is zero, this returns an empty list.");
2858
2859   ("tail", (RStringList "lines", [Pathname "path"]), 123, [ProtocolLimitWarning],
2860    [InitISOFS, Always, TestOutputList (
2861       [["tail"; "/10klines"]], ["9990abcdefghijklmnopqrstuvwxyz";"9991abcdefghijklmnopqrstuvwxyz";"9992abcdefghijklmnopqrstuvwxyz";"9993abcdefghijklmnopqrstuvwxyz";"9994abcdefghijklmnopqrstuvwxyz";"9995abcdefghijklmnopqrstuvwxyz";"9996abcdefghijklmnopqrstuvwxyz";"9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"])],
2862    "return last 10 lines of a file",
2863    "\
2864 This command returns up to the last 10 lines of a file as
2865 a list of strings.");
2866
2867   ("tail_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 124, [ProtocolLimitWarning],
2868    [InitISOFS, Always, TestOutputList (
2869       [["tail_n"; "3"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2870     InitISOFS, Always, TestOutputList (
2871       [["tail_n"; "-9998"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2872     InitISOFS, Always, TestOutputList (
2873       [["tail_n"; "0"; "/10klines"]], [])],
2874    "return last N lines of a file",
2875    "\
2876 If the parameter C<nrlines> is a positive number, this returns the last
2877 C<nrlines> lines of the file C<path>.
2878
2879 If the parameter C<nrlines> is a negative number, this returns lines
2880 from the file C<path>, starting with the C<-nrlines>th line.
2881
2882 If the parameter C<nrlines> is zero, this returns an empty list.");
2883
2884   ("df", (RString "output", []), 125, [],
2885    [], (* XXX Tricky to test because it depends on the exact format
2886         * of the 'df' command and other imponderables.
2887         *)
2888    "report file system disk space usage",
2889    "\
2890 This command runs the C<df> command to report disk space used.
2891
2892 This command is mostly useful for interactive sessions.  It
2893 is I<not> intended that you try to parse the output string.
2894 Use C<statvfs> from programs.");
2895
2896   ("df_h", (RString "output", []), 126, [],
2897    [], (* XXX Tricky to test because it depends on the exact format
2898         * of the 'df' command and other imponderables.
2899         *)
2900    "report file system disk space usage (human readable)",
2901    "\
2902 This command runs the C<df -h> command to report disk space used
2903 in human-readable format.
2904
2905 This command is mostly useful for interactive sessions.  It
2906 is I<not> intended that you try to parse the output string.
2907 Use C<statvfs> from programs.");
2908
2909   ("du", (RInt64 "sizekb", [Pathname "path"]), 127, [],
2910    [InitISOFS, Always, TestOutputInt (
2911       [["du"; "/directory"]], 2 (* ISO fs blocksize is 2K *))],
2912    "estimate file space usage",
2913    "\
2914 This command runs the C<du -s> command to estimate file space
2915 usage for C<path>.
2916
2917 C<path> can be a file or a directory.  If C<path> is a directory
2918 then the estimate includes the contents of the directory and all
2919 subdirectories (recursively).
2920
2921 The result is the estimated size in I<kilobytes>
2922 (ie. units of 1024 bytes).");
2923
2924   ("initrd_list", (RStringList "filenames", [Pathname "path"]), 128, [],
2925    [InitISOFS, Always, TestOutputList (
2926       [["initrd_list"; "/initrd"]], ["empty";"known-1";"known-2";"known-3";"known-4"; "known-5"])],
2927    "list files in an initrd",
2928    "\
2929 This command lists out files contained in an initrd.
2930
2931 The files are listed without any initial C</> character.  The
2932 files are listed in the order they appear (not necessarily
2933 alphabetical).  Directory names are listed as separate items.
2934
2935 Old Linux kernels (2.4 and earlier) used a compressed ext2
2936 filesystem as initrd.  We I<only> support the newer initramfs
2937 format (compressed cpio files).");
2938
2939   ("mount_loop", (RErr, [Pathname "file"; Pathname "mountpoint"]), 129, [],
2940    [],
2941    "mount a file using the loop device",
2942    "\
2943 This command lets you mount C<file> (a filesystem image
2944 in a file) on a mount point.  It is entirely equivalent to
2945 the command C<mount -o loop file mountpoint>.");
2946
2947   ("mkswap", (RErr, [Device "device"]), 130, [],
2948    [InitEmpty, Always, TestRun (
2949       [["part_disk"; "/dev/sda"; "mbr"];
2950        ["mkswap"; "/dev/sda1"]])],
2951    "create a swap partition",
2952    "\
2953 Create a swap partition on C<device>.");
2954
2955   ("mkswap_L", (RErr, [String "label"; Device "device"]), 131, [],
2956    [InitEmpty, Always, TestRun (
2957       [["part_disk"; "/dev/sda"; "mbr"];
2958        ["mkswap_L"; "hello"; "/dev/sda1"]])],
2959    "create a swap partition with a label",
2960    "\
2961 Create a swap partition on C<device> with label C<label>.
2962
2963 Note that you cannot attach a swap label to a block device
2964 (eg. C</dev/sda>), just to a partition.  This appears to be
2965 a limitation of the kernel or swap tools.");
2966
2967   ("mkswap_U", (RErr, [String "uuid"; Device "device"]), 132, [Optional "linuxfsuuid"],
2968    (let uuid = uuidgen () in
2969     [InitEmpty, Always, TestRun (
2970        [["part_disk"; "/dev/sda"; "mbr"];
2971         ["mkswap_U"; uuid; "/dev/sda1"]])]),
2972    "create a swap partition with an explicit UUID",
2973    "\
2974 Create a swap partition on C<device> with UUID C<uuid>.");
2975
2976   ("mknod", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 133, [Optional "mknod"],
2977    [InitBasicFS, Always, TestOutputStruct (
2978       [["mknod"; "0o10777"; "0"; "0"; "/node"];
2979        (* NB: default umask 022 means 0777 -> 0755 in these tests *)
2980        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)]);
2981     InitBasicFS, Always, TestOutputStruct (
2982       [["mknod"; "0o60777"; "66"; "99"; "/node"];
2983        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
2984    "make block, character or FIFO devices",
2985    "\
2986 This call creates block or character special devices, or
2987 named pipes (FIFOs).
2988
2989 The C<mode> parameter should be the mode, using the standard
2990 constants.  C<devmajor> and C<devminor> are the
2991 device major and minor numbers, only used when creating block
2992 and character special devices.
2993
2994 Note that, just like L<mknod(2)>, the mode must be bitwise
2995 OR'd with S_IFBLK, S_IFCHR, S_IFIFO or S_IFSOCK (otherwise this call
2996 just creates a regular file).  These constants are
2997 available in the standard Linux header files, or you can use
2998 C<guestfs_mknod_b>, C<guestfs_mknod_c> or C<guestfs_mkfifo>
2999 which are wrappers around this command which bitwise OR
3000 in the appropriate constant for you.
3001
3002 The mode actually set is affected by the umask.");
3003
3004   ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [Optional "mknod"],
3005    [InitBasicFS, Always, TestOutputStruct (
3006       [["mkfifo"; "0o777"; "/node"];
3007        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)])],
3008    "make FIFO (named pipe)",
3009    "\
3010 This call creates a FIFO (named pipe) called C<path> with
3011 mode C<mode>.  It is just a convenient wrapper around
3012 C<guestfs_mknod>.
3013
3014 The mode actually set is affected by the umask.");
3015
3016   ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [Optional "mknod"],
3017    [InitBasicFS, Always, TestOutputStruct (
3018       [["mknod_b"; "0o777"; "99"; "66"; "/node"];
3019        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
3020    "make block device node",
3021    "\
3022 This call creates a block device node called C<path> with
3023 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3024 It is just a convenient wrapper around C<guestfs_mknod>.
3025
3026 The mode actually set is affected by the umask.");
3027
3028   ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [Optional "mknod"],
3029    [InitBasicFS, Always, TestOutputStruct (
3030       [["mknod_c"; "0o777"; "99"; "66"; "/node"];
3031        ["stat"; "/node"]], [CompareWithInt ("mode", 0o20755)])],
3032    "make char device node",
3033    "\
3034 This call creates a char device node called C<path> with
3035 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3036 It is just a convenient wrapper around C<guestfs_mknod>.
3037
3038 The mode actually set is affected by the umask.");
3039
3040   ("umask", (RInt "oldmask", [Int "mask"]), 137, [FishOutput FishOutputOctal],
3041    [InitEmpty, Always, TestOutputInt (
3042       [["umask"; "0o22"]], 0o22)],
3043    "set file mode creation mask (umask)",
3044    "\
3045 This function sets the mask used for creating new files and
3046 device nodes to C<mask & 0777>.
3047
3048 Typical umask values would be C<022> which creates new files
3049 with permissions like \"-rw-r--r--\" or \"-rwxr-xr-x\", and
3050 C<002> which creates new files with permissions like
3051 \"-rw-rw-r--\" or \"-rwxrwxr-x\".
3052
3053 The default umask is C<022>.  This is important because it
3054 means that directories and device nodes will be created with
3055 C<0644> or C<0755> mode even if you specify C<0777>.
3056
3057 See also C<guestfs_get_umask>,
3058 L<umask(2)>, C<guestfs_mknod>, C<guestfs_mkdir>.
3059
3060 This call returns the previous umask.");
3061
3062   ("readdir", (RStructList ("entries", "dirent"), [Pathname "dir"]), 138, [],
3063    [],
3064    "read directories entries",
3065    "\
3066 This returns the list of directory entries in directory C<dir>.
3067
3068 All entries in the directory are returned, including C<.> and
3069 C<..>.  The entries are I<not> sorted, but returned in the same
3070 order as the underlying filesystem.
3071
3072 Also this call returns basic file type information about each
3073 file.  The C<ftyp> field will contain one of the following characters:
3074
3075 =over 4
3076
3077 =item 'b'
3078
3079 Block special
3080
3081 =item 'c'
3082
3083 Char special
3084
3085 =item 'd'
3086
3087 Directory
3088
3089 =item 'f'
3090
3091 FIFO (named pipe)
3092
3093 =item 'l'
3094
3095 Symbolic link
3096
3097 =item 'r'
3098
3099 Regular file
3100
3101 =item 's'
3102
3103 Socket
3104
3105 =item 'u'
3106
3107 Unknown file type
3108
3109 =item '?'
3110
3111 The L<readdir(3)> returned a C<d_type> field with an
3112 unexpected value
3113
3114 =back
3115
3116 This function is primarily intended for use by programs.  To
3117 get a simple list of names, use C<guestfs_ls>.  To get a printable
3118 directory for human consumption, use C<guestfs_ll>.");
3119
3120   ("sfdiskM", (RErr, [Device "device"; StringList "lines"]), 139, [DangerWillRobinson],
3121    [],
3122    "create partitions on a block device",
3123    "\
3124 This is a simplified interface to the C<guestfs_sfdisk>
3125 command, where partition sizes are specified in megabytes
3126 only (rounded to the nearest cylinder) and you don't need
3127 to specify the cyls, heads and sectors parameters which
3128 were rarely if ever used anyway.
3129
3130 See also: C<guestfs_sfdisk>, the L<sfdisk(8)> manpage
3131 and C<guestfs_part_disk>");
3132
3133   ("zfile", (RString "description", [String "meth"; Pathname "path"]), 140, [DeprecatedBy "file"],
3134    [],
3135    "determine file type inside a compressed file",
3136    "\
3137 This command runs C<file> after first decompressing C<path>
3138 using C<method>.
3139
3140 C<method> must be one of C<gzip>, C<compress> or C<bzip2>.
3141
3142 Since 1.0.63, use C<guestfs_file> instead which can now
3143 process compressed files.");
3144
3145   ("getxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 141, [Optional "linuxxattrs"],
3146    [],
3147    "list extended attributes of a file or directory",
3148    "\
3149 This call lists the extended attributes of the file or directory
3150 C<path>.
3151
3152 At the system call level, this is a combination of the
3153 L<listxattr(2)> and L<getxattr(2)> calls.
3154
3155 See also: C<guestfs_lgetxattrs>, L<attr(5)>.");
3156
3157   ("lgetxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 142, [Optional "linuxxattrs"],
3158    [],
3159    "list extended attributes of a file or directory",
3160    "\
3161 This is the same as C<guestfs_getxattrs>, but if C<path>
3162 is a symbolic link, then it returns the extended attributes
3163 of the link itself.");
3164
3165   ("setxattr", (RErr, [String "xattr";
3166                        String "val"; Int "vallen"; (* will be BufferIn *)
3167                        Pathname "path"]), 143, [Optional "linuxxattrs"],
3168    [],
3169    "set extended attribute of a file or directory",
3170    "\
3171 This call sets the extended attribute named C<xattr>
3172 of the file C<path> to the value C<val> (of length C<vallen>).
3173 The value is arbitrary 8 bit data.
3174
3175 See also: C<guestfs_lsetxattr>, L<attr(5)>.");
3176
3177   ("lsetxattr", (RErr, [String "xattr";
3178                         String "val"; Int "vallen"; (* will be BufferIn *)
3179                         Pathname "path"]), 144, [Optional "linuxxattrs"],
3180    [],
3181    "set extended attribute of a file or directory",
3182    "\
3183 This is the same as C<guestfs_setxattr>, but if C<path>
3184 is a symbolic link, then it sets an extended attribute
3185 of the link itself.");
3186
3187   ("removexattr", (RErr, [String "xattr"; Pathname "path"]), 145, [Optional "linuxxattrs"],
3188    [],
3189    "remove extended attribute of a file or directory",
3190    "\
3191 This call removes the extended attribute named C<xattr>
3192 of the file C<path>.
3193
3194 See also: C<guestfs_lremovexattr>, L<attr(5)>.");
3195
3196   ("lremovexattr", (RErr, [String "xattr"; Pathname "path"]), 146, [Optional "linuxxattrs"],
3197    [],
3198    "remove extended attribute of a file or directory",
3199    "\
3200 This is the same as C<guestfs_removexattr>, but if C<path>
3201 is a symbolic link, then it removes an extended attribute
3202 of the link itself.");
3203
3204   ("mountpoints", (RHashtable "mps", []), 147, [],
3205    [],
3206    "show mountpoints",
3207    "\
3208 This call is similar to C<guestfs_mounts>.  That call returns
3209 a list of devices.  This one returns a hash table (map) of
3210 device name to directory where the device is mounted.");
3211
3212   ("mkmountpoint", (RErr, [String "exemptpath"]), 148, [],
3213    (* This is a special case: while you would expect a parameter
3214     * of type "Pathname", that doesn't work, because it implies
3215     * NEED_ROOT in the generated calling code in stubs.c, and
3216     * this function cannot use NEED_ROOT.
3217     *)
3218    [],
3219    "create a mountpoint",
3220    "\
3221 C<guestfs_mkmountpoint> and C<guestfs_rmmountpoint> are
3222 specialized calls that can be used to create extra mountpoints
3223 before mounting the first filesystem.
3224
3225 These calls are I<only> necessary in some very limited circumstances,
3226 mainly the case where you want to mount a mix of unrelated and/or
3227 read-only filesystems together.
3228
3229 For example, live CDs often contain a \"Russian doll\" nest of
3230 filesystems, an ISO outer layer, with a squashfs image inside, with
3231 an ext2/3 image inside that.  You can unpack this as follows
3232 in guestfish:
3233
3234  add-ro Fedora-11-i686-Live.iso
3235  run
3236  mkmountpoint /cd
3237  mkmountpoint /squash
3238  mkmountpoint /ext3
3239  mount /dev/sda /cd
3240  mount-loop /cd/LiveOS/squashfs.img /squash
3241  mount-loop /squash/LiveOS/ext3fs.img /ext3
3242
3243 The inner filesystem is now unpacked under the /ext3 mountpoint.");
3244
3245   ("rmmountpoint", (RErr, [String "exemptpath"]), 149, [],
3246    [],
3247    "remove a mountpoint",
3248    "\
3249 This calls removes a mountpoint that was previously created
3250 with C<guestfs_mkmountpoint>.  See C<guestfs_mkmountpoint>
3251 for full details.");
3252
3253   ("read_file", (RBufferOut "content", [Pathname "path"]), 150, [ProtocolLimitWarning],
3254    [InitISOFS, Always, TestOutputBuffer (
3255       [["read_file"; "/known-4"]], "abc\ndef\nghi")],
3256    "read a file",
3257    "\
3258 This calls returns the contents of the file C<path> as a
3259 buffer.
3260
3261 Unlike C<guestfs_cat>, this function can correctly
3262 handle files that contain embedded ASCII NUL characters.
3263 However unlike C<guestfs_download>, this function is limited
3264 in the total size of file that can be handled.");
3265
3266   ("grep", (RStringList "lines", [String "regex"; Pathname "path"]), 151, [ProtocolLimitWarning],
3267    [InitISOFS, Always, TestOutputList (
3268       [["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]);
3269     InitISOFS, Always, TestOutputList (
3270       [["grep"; "nomatch"; "/test-grep.txt"]], [])],
3271    "return lines matching a pattern",
3272    "\
3273 This calls the external C<grep> program and returns the
3274 matching lines.");
3275
3276   ("egrep", (RStringList "lines", [String "regex"; Pathname "path"]), 152, [ProtocolLimitWarning],
3277    [InitISOFS, Always, TestOutputList (
3278       [["egrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3279    "return lines matching a pattern",
3280    "\
3281 This calls the external C<egrep> program and returns the
3282 matching lines.");
3283
3284   ("fgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 153, [ProtocolLimitWarning],
3285    [InitISOFS, Always, TestOutputList (
3286       [["fgrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3287    "return lines matching a pattern",
3288    "\
3289 This calls the external C<fgrep> program and returns the
3290 matching lines.");
3291
3292   ("grepi", (RStringList "lines", [String "regex"; Pathname "path"]), 154, [ProtocolLimitWarning],
3293    [InitISOFS, Always, TestOutputList (
3294       [["grepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3295    "return lines matching a pattern",
3296    "\
3297 This calls the external C<grep -i> program and returns the
3298 matching lines.");
3299
3300   ("egrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 155, [ProtocolLimitWarning],
3301    [InitISOFS, Always, TestOutputList (
3302       [["egrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3303    "return lines matching a pattern",
3304    "\
3305 This calls the external C<egrep -i> program and returns the
3306 matching lines.");
3307
3308   ("fgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 156, [ProtocolLimitWarning],
3309    [InitISOFS, Always, TestOutputList (
3310       [["fgrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3311    "return lines matching a pattern",
3312    "\
3313 This calls the external C<fgrep -i> program and returns the
3314 matching lines.");
3315
3316   ("zgrep", (RStringList "lines", [String "regex"; Pathname "path"]), 157, [ProtocolLimitWarning],
3317    [InitISOFS, Always, TestOutputList (
3318       [["zgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3319    "return lines matching a pattern",
3320    "\
3321 This calls the external C<zgrep> program and returns the
3322 matching lines.");
3323
3324   ("zegrep", (RStringList "lines", [String "regex"; Pathname "path"]), 158, [ProtocolLimitWarning],
3325    [InitISOFS, Always, TestOutputList (
3326       [["zegrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3327    "return lines matching a pattern",
3328    "\
3329 This calls the external C<zegrep> program and returns the
3330 matching lines.");
3331
3332   ("zfgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 159, [ProtocolLimitWarning],
3333    [InitISOFS, Always, TestOutputList (
3334       [["zfgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3335    "return lines matching a pattern",
3336    "\
3337 This calls the external C<zfgrep> program and returns the
3338 matching lines.");
3339
3340   ("zgrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 160, [ProtocolLimitWarning],
3341    [InitISOFS, Always, TestOutputList (
3342       [["zgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3343    "return lines matching a pattern",
3344    "\
3345 This calls the external C<zgrep -i> program and returns the
3346 matching lines.");
3347
3348   ("zegrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 161, [ProtocolLimitWarning],
3349    [InitISOFS, Always, TestOutputList (
3350       [["zegrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3351    "return lines matching a pattern",
3352    "\
3353 This calls the external C<zegrep -i> program and returns the
3354 matching lines.");
3355
3356   ("zfgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 162, [ProtocolLimitWarning],
3357    [InitISOFS, Always, TestOutputList (
3358       [["zfgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3359    "return lines matching a pattern",
3360    "\
3361 This calls the external C<zfgrep -i> program and returns the
3362 matching lines.");
3363
3364   ("realpath", (RString "rpath", [Pathname "path"]), 163, [Optional "realpath"],
3365    [InitISOFS, Always, TestOutput (
3366       [["realpath"; "/../directory"]], "/directory")],
3367    "canonicalized absolute pathname",
3368    "\
3369 Return the canonicalized absolute pathname of C<path>.  The
3370 returned path has no C<.>, C<..> or symbolic link path elements.");
3371
3372   ("ln", (RErr, [String "target"; Pathname "linkname"]), 164, [],
3373    [InitBasicFS, Always, TestOutputStruct (
3374       [["touch"; "/a"];
3375        ["ln"; "/a"; "/b"];
3376        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3377    "create a hard link",
3378    "\
3379 This command creates a hard link using the C<ln> command.");
3380
3381   ("ln_f", (RErr, [String "target"; Pathname "linkname"]), 165, [],
3382    [InitBasicFS, Always, TestOutputStruct (
3383       [["touch"; "/a"];
3384        ["touch"; "/b"];
3385        ["ln_f"; "/a"; "/b"];
3386        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3387    "create a hard link",
3388    "\
3389 This command creates a hard link using the C<ln -f> command.
3390 The C<-f> option removes the link (C<linkname>) if it exists already.");
3391
3392   ("ln_s", (RErr, [String "target"; Pathname "linkname"]), 166, [],
3393    [InitBasicFS, Always, TestOutputStruct (
3394       [["touch"; "/a"];
3395        ["ln_s"; "a"; "/b"];
3396        ["lstat"; "/b"]], [CompareWithInt ("mode", 0o120777)])],
3397    "create a symbolic link",
3398    "\
3399 This command creates a symbolic link using the C<ln -s> command.");
3400
3401   ("ln_sf", (RErr, [String "target"; Pathname "linkname"]), 167, [],
3402    [InitBasicFS, Always, TestOutput (
3403       [["mkdir_p"; "/a/b"];
3404        ["touch"; "/a/b/c"];
3405        ["ln_sf"; "../d"; "/a/b/c"];
3406        ["readlink"; "/a/b/c"]], "../d")],
3407    "create a symbolic link",
3408    "\
3409 This command creates a symbolic link using the C<ln -sf> command,
3410 The C<-f> option removes the link (C<linkname>) if it exists already.");
3411
3412   ("readlink", (RString "link", [Pathname "path"]), 168, [],
3413    [] (* XXX tested above *),
3414    "read the target of a symbolic link",
3415    "\
3416 This command reads the target of a symbolic link.");
3417
3418   ("fallocate", (RErr, [Pathname "path"; Int "len"]), 169, [],
3419    [InitBasicFS, Always, TestOutputStruct (
3420       [["fallocate"; "/a"; "1000000"];
3421        ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
3422    "preallocate a file in the guest filesystem",
3423    "\
3424 This command preallocates a file (containing zero bytes) named
3425 C<path> of size C<len> bytes.  If the file exists already, it
3426 is overwritten.
3427
3428 Do not confuse this with the guestfish-specific
3429 C<alloc> command which allocates a file in the host and
3430 attaches it as a device.");
3431
3432   ("swapon_device", (RErr, [Device "device"]), 170, [],
3433    [InitPartition, Always, TestRun (
3434       [["mkswap"; "/dev/sda1"];
3435        ["swapon_device"; "/dev/sda1"];
3436        ["swapoff_device"; "/dev/sda1"]])],
3437    "enable swap on device",
3438    "\
3439 This command enables the libguestfs appliance to use the
3440 swap device or partition named C<device>.  The increased
3441 memory is made available for all commands, for example
3442 those run using C<guestfs_command> or C<guestfs_sh>.
3443
3444 Note that you should not swap to existing guest swap
3445 partitions unless you know what you are doing.  They may
3446 contain hibernation information, or other information that
3447 the guest doesn't want you to trash.  You also risk leaking
3448 information about the host to the guest this way.  Instead,
3449 attach a new host device to the guest and swap on that.");
3450
3451   ("swapoff_device", (RErr, [Device "device"]), 171, [],
3452    [], (* XXX tested by swapon_device *)
3453    "disable swap on device",
3454    "\
3455 This command disables the libguestfs appliance swap
3456 device or partition named C<device>.
3457 See C<guestfs_swapon_device>.");
3458
3459   ("swapon_file", (RErr, [Pathname "file"]), 172, [],
3460    [InitBasicFS, Always, TestRun (
3461       [["fallocate"; "/swap"; "8388608"];
3462        ["mkswap_file"; "/swap"];
3463        ["swapon_file"; "/swap"];
3464        ["swapoff_file"; "/swap"]])],
3465    "enable swap on file",
3466    "\
3467 This command enables swap to a file.
3468 See C<guestfs_swapon_device> for other notes.");
3469
3470   ("swapoff_file", (RErr, [Pathname "file"]), 173, [],
3471    [], (* XXX tested by swapon_file *)
3472    "disable swap on file",
3473    "\
3474 This command disables the libguestfs appliance swap on file.");
3475
3476   ("swapon_label", (RErr, [String "label"]), 174, [],
3477    [InitEmpty, Always, TestRun (
3478       [["part_disk"; "/dev/sdb"; "mbr"];
3479        ["mkswap_L"; "swapit"; "/dev/sdb1"];
3480        ["swapon_label"; "swapit"];
3481        ["swapoff_label"; "swapit"];
3482        ["zero"; "/dev/sdb"];
3483        ["blockdev_rereadpt"; "/dev/sdb"]])],
3484    "enable swap on labeled swap partition",
3485    "\
3486 This command enables swap to a labeled swap partition.
3487 See C<guestfs_swapon_device> for other notes.");
3488
3489   ("swapoff_label", (RErr, [String "label"]), 175, [],
3490    [], (* XXX tested by swapon_label *)
3491    "disable swap on labeled swap partition",
3492    "\
3493 This command disables the libguestfs appliance swap on
3494 labeled swap partition.");
3495
3496   ("swapon_uuid", (RErr, [String "uuid"]), 176, [Optional "linuxfsuuid"],
3497    (let uuid = uuidgen () in
3498     [InitEmpty, Always, TestRun (
3499        [["mkswap_U"; uuid; "/dev/sdb"];
3500         ["swapon_uuid"; uuid];
3501         ["swapoff_uuid"; uuid]])]),
3502    "enable swap on swap partition by UUID",
3503    "\
3504 This command enables swap to a swap partition with the given UUID.
3505 See C<guestfs_swapon_device> for other notes.");
3506
3507   ("swapoff_uuid", (RErr, [String "uuid"]), 177, [Optional "linuxfsuuid"],
3508    [], (* XXX tested by swapon_uuid *)
3509    "disable swap on swap partition by UUID",
3510    "\
3511 This command disables the libguestfs appliance swap partition
3512 with the given UUID.");
3513
3514   ("mkswap_file", (RErr, [Pathname "path"]), 178, [],
3515    [InitBasicFS, Always, TestRun (
3516       [["fallocate"; "/swap"; "8388608"];
3517        ["mkswap_file"; "/swap"]])],
3518    "create a swap file",
3519    "\
3520 Create a swap file.
3521
3522 This command just writes a swap file signature to an existing
3523 file.  To create the file itself, use something like C<guestfs_fallocate>.");
3524
3525   ("inotify_init", (RErr, [Int "maxevents"]), 179, [Optional "inotify"],
3526    [InitISOFS, Always, TestRun (
3527       [["inotify_init"; "0"]])],
3528    "create an inotify handle",
3529    "\
3530 This command creates a new inotify handle.
3531 The inotify subsystem can be used to notify events which happen to
3532 objects in the guest filesystem.
3533
3534 C<maxevents> is the maximum number of events which will be
3535 queued up between calls to C<guestfs_inotify_read> or
3536 C<guestfs_inotify_files>.
3537 If this is passed as C<0>, then the kernel (or previously set)
3538 default is used.  For Linux 2.6.29 the default was 16384 events.
3539 Beyond this limit, the kernel throws away events, but records
3540 the fact that it threw them away by setting a flag
3541 C<IN_Q_OVERFLOW> in the returned structure list (see
3542 C<guestfs_inotify_read>).
3543
3544 Before any events are generated, you have to add some
3545 watches to the internal watch list.  See:
3546 C<guestfs_inotify_add_watch>,
3547 C<guestfs_inotify_rm_watch> and
3548 C<guestfs_inotify_watch_all>.
3549
3550 Queued up events should be read periodically by calling
3551 C<guestfs_inotify_read>
3552 (or C<guestfs_inotify_files> which is just a helpful
3553 wrapper around C<guestfs_inotify_read>).  If you don't
3554 read the events out often enough then you risk the internal
3555 queue overflowing.
3556
3557 The handle should be closed after use by calling
3558 C<guestfs_inotify_close>.  This also removes any
3559 watches automatically.
3560
3561 See also L<inotify(7)> for an overview of the inotify interface
3562 as exposed by the Linux kernel, which is roughly what we expose
3563 via libguestfs.  Note that there is one global inotify handle
3564 per libguestfs instance.");
3565
3566   ("inotify_add_watch", (RInt64 "wd", [Pathname "path"; Int "mask"]), 180, [Optional "inotify"],
3567    [InitBasicFS, Always, TestOutputList (
3568       [["inotify_init"; "0"];
3569        ["inotify_add_watch"; "/"; "1073741823"];
3570        ["touch"; "/a"];
3571        ["touch"; "/b"];
3572        ["inotify_files"]], ["a"; "b"])],
3573    "add an inotify watch",
3574    "\
3575 Watch C<path> for the events listed in C<mask>.
3576
3577 Note that if C<path> is a directory then events within that
3578 directory are watched, but this does I<not> happen recursively
3579 (in subdirectories).
3580
3581 Note for non-C or non-Linux callers: the inotify events are
3582 defined by the Linux kernel ABI and are listed in
3583 C</usr/include/sys/inotify.h>.");
3584
3585   ("inotify_rm_watch", (RErr, [Int(*XXX64*) "wd"]), 181, [Optional "inotify"],
3586    [],
3587    "remove an inotify watch",
3588    "\
3589 Remove a previously defined inotify watch.
3590 See C<guestfs_inotify_add_watch>.");
3591
3592   ("inotify_read", (RStructList ("events", "inotify_event"), []), 182, [Optional "inotify"],
3593    [],
3594    "return list of inotify events",
3595    "\
3596 Return the complete queue of events that have happened
3597 since the previous read call.
3598
3599 If no events have happened, this returns an empty list.
3600
3601 I<Note>: In order to make sure that all events have been
3602 read, you must call this function repeatedly until it
3603 returns an empty list.  The reason is that the call will
3604 read events up to the maximum appliance-to-host message
3605 size and leave remaining events in the queue.");
3606
3607   ("inotify_files", (RStringList "paths", []), 183, [Optional "inotify"],
3608    [],
3609    "return list of watched files that had events",
3610    "\
3611 This function is a helpful wrapper around C<guestfs_inotify_read>
3612 which just returns a list of pathnames of objects that were
3613 touched.  The returned pathnames are sorted and deduplicated.");
3614
3615   ("inotify_close", (RErr, []), 184, [Optional "inotify"],
3616    [],
3617    "close the inotify handle",
3618    "\
3619 This closes the inotify handle which was previously
3620 opened by inotify_init.  It removes all watches, throws
3621 away any pending events, and deallocates all resources.");
3622
3623   ("setcon", (RErr, [String "context"]), 185, [Optional "selinux"],
3624    [],
3625    "set SELinux security context",
3626    "\
3627 This sets the SELinux security context of the daemon
3628 to the string C<context>.
3629
3630 See the documentation about SELINUX in L<guestfs(3)>.");
3631
3632   ("getcon", (RString "context", []), 186, [Optional "selinux"],
3633    [],
3634    "get SELinux security context",
3635    "\
3636 This gets the SELinux security context of the daemon.
3637
3638 See the documentation about SELINUX in L<guestfs(3)>,
3639 and C<guestfs_setcon>");
3640
3641   ("mkfs_b", (RErr, [String "fstype"; Int "blocksize"; Device "device"]), 187, [],
3642    [InitEmpty, Always, TestOutput (
3643       [["part_disk"; "/dev/sda"; "mbr"];
3644        ["mkfs_b"; "ext2"; "4096"; "/dev/sda1"];
3645        ["mount_options"; ""; "/dev/sda1"; "/"];
3646        ["write_file"; "/new"; "new file contents"; "0"];
3647        ["cat"; "/new"]], "new file contents")],
3648    "make a filesystem with block size",
3649    "\
3650 This call is similar to C<guestfs_mkfs>, but it allows you to
3651 control the block size of the resulting filesystem.  Supported
3652 block sizes depend on the filesystem type, but typically they
3653 are C<1024>, C<2048> or C<4096> only.");
3654
3655   ("mke2journal", (RErr, [Int "blocksize"; Device "device"]), 188, [],
3656    [InitEmpty, Always, TestOutput (
3657       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3658        ["mke2journal"; "4096"; "/dev/sda1"];
3659        ["mke2fs_J"; "ext2"; "4096"; "/dev/sda2"; "/dev/sda1"];
3660        ["mount_options"; ""; "/dev/sda2"; "/"];
3661        ["write_file"; "/new"; "new file contents"; "0"];
3662        ["cat"; "/new"]], "new file contents")],
3663    "make ext2/3/4 external journal",
3664    "\
3665 This creates an ext2 external journal on C<device>.  It is equivalent
3666 to the command:
3667
3668  mke2fs -O journal_dev -b blocksize device");
3669
3670   ("mke2journal_L", (RErr, [Int "blocksize"; String "label"; Device "device"]), 189, [],
3671    [InitEmpty, Always, TestOutput (
3672       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3673        ["mke2journal_L"; "4096"; "JOURNAL"; "/dev/sda1"];
3674        ["mke2fs_JL"; "ext2"; "4096"; "/dev/sda2"; "JOURNAL"];
3675        ["mount_options"; ""; "/dev/sda2"; "/"];
3676        ["write_file"; "/new"; "new file contents"; "0"];
3677        ["cat"; "/new"]], "new file contents")],
3678    "make ext2/3/4 external journal with label",
3679    "\
3680 This creates an ext2 external journal on C<device> with label C<label>.");
3681
3682   ("mke2journal_U", (RErr, [Int "blocksize"; String "uuid"; Device "device"]), 190, [Optional "linuxfsuuid"],
3683    (let uuid = uuidgen () in
3684     [InitEmpty, Always, TestOutput (
3685        [["sfdiskM"; "/dev/sda"; ",100 ,"];
3686         ["mke2journal_U"; "4096"; uuid; "/dev/sda1"];
3687         ["mke2fs_JU"; "ext2"; "4096"; "/dev/sda2"; uuid];
3688         ["mount_options"; ""; "/dev/sda2"; "/"];
3689         ["write_file"; "/new"; "new file contents"; "0"];
3690         ["cat"; "/new"]], "new file contents")]),
3691    "make ext2/3/4 external journal with UUID",
3692    "\
3693 This creates an ext2 external journal on C<device> with UUID C<uuid>.");
3694
3695   ("mke2fs_J", (RErr, [String "fstype"; Int "blocksize"; Device "device"; Device "journal"]), 191, [],
3696    [],
3697    "make ext2/3/4 filesystem with external journal",
3698    "\
3699 This creates an ext2/3/4 filesystem on C<device> with
3700 an external journal on C<journal>.  It is equivalent
3701 to the command:
3702
3703  mke2fs -t fstype -b blocksize -J device=<journal> <device>
3704
3705 See also C<guestfs_mke2journal>.");
3706
3707   ("mke2fs_JL", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "label"]), 192, [],
3708    [],
3709    "make ext2/3/4 filesystem with external journal",
3710    "\
3711 This creates an ext2/3/4 filesystem on C<device> with
3712 an external journal on the journal labeled C<label>.
3713
3714 See also C<guestfs_mke2journal_L>.");
3715
3716   ("mke2fs_JU", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "uuid"]), 193, [Optional "linuxfsuuid"],
3717    [],
3718    "make ext2/3/4 filesystem with external journal",
3719    "\
3720 This creates an ext2/3/4 filesystem on C<device> with
3721 an external journal on the journal with UUID C<uuid>.
3722
3723 See also C<guestfs_mke2journal_U>.");
3724
3725   ("modprobe", (RErr, [String "modulename"]), 194, [Optional "linuxmodules"],
3726    [InitNone, Always, TestRun [["modprobe"; "fat"]]],
3727    "load a kernel module",
3728    "\
3729 This loads a kernel module in the appliance.
3730
3731 The kernel module must have been whitelisted when libguestfs
3732 was built (see C<appliance/kmod.whitelist.in> in the source).");
3733
3734   ("echo_daemon", (RString "output", [StringList "words"]), 195, [],
3735    [InitNone, Always, TestOutput (
3736       [["echo_daemon"; "This is a test"]], "This is a test"
3737     )],
3738    "echo arguments back to the client",
3739    "\
3740 This command concatenate the list of C<words> passed with single spaces between
3741 them and returns the resulting string.
3742
3743 You can use this command to test the connection through to the daemon.
3744
3745 See also C<guestfs_ping_daemon>.");
3746
3747   ("find0", (RErr, [Pathname "directory"; FileOut "files"]), 196, [],
3748    [], (* There is a regression test for this. *)
3749    "find all files and directories, returning NUL-separated list",
3750    "\
3751 This command lists out all files and directories, recursively,
3752 starting at C<directory>, placing the resulting list in the
3753 external file called C<files>.
3754
3755 This command works the same way as C<guestfs_find> with the
3756 following exceptions:
3757
3758 =over 4
3759
3760 =item *
3761
3762 The resulting list is written to an external file.
3763
3764 =item *
3765
3766 Items (filenames) in the result are separated
3767 by C<\\0> characters.  See L<find(1)> option I<-print0>.
3768
3769 =item *
3770
3771 This command is not limited in the number of names that it
3772 can return.
3773
3774 =item *
3775
3776 The result list is not sorted.
3777
3778 =back");
3779
3780   ("case_sensitive_path", (RString "rpath", [Pathname "path"]), 197, [],
3781    [InitISOFS, Always, TestOutput (
3782       [["case_sensitive_path"; "/DIRECTORY"]], "/directory");
3783     InitISOFS, Always, TestOutput (
3784       [["case_sensitive_path"; "/DIRECTORY/"]], "/directory");
3785     InitISOFS, Always, TestOutput (
3786       [["case_sensitive_path"; "/Known-1"]], "/known-1");
3787     InitISOFS, Always, TestLastFail (
3788       [["case_sensitive_path"; "/Known-1/"]]);
3789     InitBasicFS, Always, TestOutput (
3790       [["mkdir"; "/a"];
3791        ["mkdir"; "/a/bbb"];
3792        ["touch"; "/a/bbb/c"];
3793        ["case_sensitive_path"; "/A/bbB/C"]], "/a/bbb/c");
3794     InitBasicFS, Always, TestOutput (
3795       [["mkdir"; "/a"];
3796        ["mkdir"; "/a/bbb"];
3797        ["touch"; "/a/bbb/c"];
3798        ["case_sensitive_path"; "/A////bbB/C"]], "/a/bbb/c");
3799     InitBasicFS, Always, TestLastFail (
3800       [["mkdir"; "/a"];
3801        ["mkdir"; "/a/bbb"];
3802        ["touch"; "/a/bbb/c"];
3803        ["case_sensitive_path"; "/A/bbb/../bbb/C"]])],
3804    "return true path on case-insensitive filesystem",
3805    "\
3806 This can be used to resolve case insensitive paths on
3807 a filesystem which is case sensitive.  The use case is
3808 to resolve paths which you have read from Windows configuration
3809 files or the Windows Registry, to the true path.
3810
3811 The command handles a peculiarity of the Linux ntfs-3g
3812 filesystem driver (and probably others), which is that although
3813 the underlying filesystem is case-insensitive, the driver
3814 exports the filesystem to Linux as case-sensitive.
3815
3816 One consequence of this is that special directories such
3817 as C<c:\\windows> may appear as C</WINDOWS> or C</windows>
3818 (or other things) depending on the precise details of how
3819 they were created.  In Windows itself this would not be
3820 a problem.
3821
3822 Bug or feature?  You decide:
3823 L<http://www.tuxera.com/community/ntfs-3g-faq/#posixfilenames1>
3824
3825 This function resolves the true case of each element in the
3826 path and returns the case-sensitive path.
3827
3828 Thus C<guestfs_case_sensitive_path> (\"/Windows/System32\")
3829 might return C<\"/WINDOWS/system32\"> (the exact return value
3830 would depend on details of how the directories were originally
3831 created under Windows).
3832
3833 I<Note>:
3834 This function does not handle drive names, backslashes etc.
3835
3836 See also C<guestfs_realpath>.");
3837
3838   ("vfs_type", (RString "fstype", [Device "device"]), 198, [],
3839    [InitBasicFS, Always, TestOutput (
3840       [["vfs_type"; "/dev/sda1"]], "ext2")],
3841    "get the Linux VFS type corresponding to a mounted device",
3842    "\
3843 This command gets the block device type corresponding to
3844 a mounted device called C<device>.
3845
3846 Usually the result is the name of the Linux VFS module that
3847 is used to mount this device (probably determined automatically
3848 if you used the C<guestfs_mount> call).");
3849
3850   ("truncate", (RErr, [Pathname "path"]), 199, [],
3851    [InitBasicFS, Always, TestOutputStruct (
3852       [["write_file"; "/test"; "some stuff so size is not zero"; "0"];
3853        ["truncate"; "/test"];
3854        ["stat"; "/test"]], [CompareWithInt ("size", 0)])],
3855    "truncate a file to zero size",
3856    "\
3857 This command truncates C<path> to a zero-length file.  The
3858 file must exist already.");
3859
3860   ("truncate_size", (RErr, [Pathname "path"; Int64 "size"]), 200, [],
3861    [InitBasicFS, Always, TestOutputStruct (
3862       [["touch"; "/test"];
3863        ["truncate_size"; "/test"; "1000"];
3864        ["stat"; "/test"]], [CompareWithInt ("size", 1000)])],
3865    "truncate a file to a particular size",
3866    "\
3867 This command truncates C<path> to size C<size> bytes.  The file
3868 must exist already.  If the file is smaller than C<size> then
3869 the file is extended to the required size with null bytes.");
3870
3871   ("utimens", (RErr, [Pathname "path"; Int64 "atsecs"; Int64 "atnsecs"; Int64 "mtsecs"; Int64 "mtnsecs"]), 201, [],
3872    [InitBasicFS, Always, TestOutputStruct (
3873       [["touch"; "/test"];
3874        ["utimens"; "/test"; "12345"; "67890"; "9876"; "5432"];
3875        ["stat"; "/test"]], [CompareWithInt ("mtime", 9876)])],
3876    "set timestamp of a file with nanosecond precision",
3877    "\
3878 This command sets the timestamps of a file with nanosecond
3879 precision.
3880
3881 C<atsecs, atnsecs> are the last access time (atime) in secs and
3882 nanoseconds from the epoch.
3883
3884 C<mtsecs, mtnsecs> are the last modification time (mtime) in
3885 secs and nanoseconds from the epoch.
3886
3887 If the C<*nsecs> field contains the special value C<-1> then
3888 the corresponding timestamp is set to the current time.  (The
3889 C<*secs> field is ignored in this case).
3890
3891 If the C<*nsecs> field contains the special value C<-2> then
3892 the corresponding timestamp is left unchanged.  (The
3893 C<*secs> field is ignored in this case).");
3894
3895   ("mkdir_mode", (RErr, [Pathname "path"; Int "mode"]), 202, [],
3896    [InitBasicFS, Always, TestOutputStruct (
3897       [["mkdir_mode"; "/test"; "0o111"];
3898        ["stat"; "/test"]], [CompareWithInt ("mode", 0o40111)])],
3899    "create a directory with a particular mode",
3900    "\
3901 This command creates a directory, setting the initial permissions
3902 of the directory to C<mode>.
3903
3904 For common Linux filesystems, the actual mode which is set will
3905 be C<mode & ~umask & 01777>.  Non-native-Linux filesystems may
3906 interpret the mode in other ways.
3907
3908 See also C<guestfs_mkdir>, C<guestfs_umask>");
3909
3910   ("lchown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 203, [],
3911    [], (* XXX *)
3912    "change file owner and group",
3913    "\
3914 Change the file owner to C<owner> and group to C<group>.
3915 This is like C<guestfs_chown> but if C<path> is a symlink then
3916 the link itself is changed, not the target.
3917
3918 Only numeric uid and gid are supported.  If you want to use
3919 names, you will need to locate and parse the password file
3920 yourself (Augeas support makes this relatively easy).");
3921
3922   ("lstatlist", (RStructList ("statbufs", "stat"), [Pathname "path"; StringList "names"]), 204, [],
3923    [], (* XXX *)
3924    "lstat on multiple files",
3925    "\
3926 This call allows you to perform the C<guestfs_lstat> operation
3927 on multiple files, where all files are in the directory C<path>.
3928 C<names> is the list of files from this directory.
3929
3930 On return you get a list of stat structs, with a one-to-one
3931 correspondence to the C<names> list.  If any name did not exist
3932 or could not be lstat'd, then the C<ino> field of that structure
3933 is set to C<-1>.
3934
3935 This call is intended for programs that want to efficiently
3936 list a directory contents without making many round-trips.
3937 See also C<guestfs_lxattrlist> for a similarly efficient call
3938 for getting extended attributes.  Very long directory listings
3939 might cause the protocol message size to be exceeded, causing
3940 this call to fail.  The caller must split up such requests
3941 into smaller groups of names.");
3942
3943   ("lxattrlist", (RStructList ("xattrs", "xattr"), [Pathname "path"; StringList "names"]), 205, [Optional "linuxxattrs"],
3944    [], (* XXX *)
3945    "lgetxattr on multiple files",
3946    "\
3947 This call allows you to get the extended attributes
3948 of multiple files, where all files are in the directory C<path>.
3949 C<names> is the list of files from this directory.
3950
3951 On return you get a flat list of xattr structs which must be
3952 interpreted sequentially.  The first xattr struct always has a zero-length
3953 C<attrname>.  C<attrval> in this struct is zero-length
3954 to indicate there was an error doing C<lgetxattr> for this
3955 file, I<or> is a C string which is a decimal number
3956 (the number of following attributes for this file, which could
3957 be C<\"0\">).  Then after the first xattr struct are the
3958 zero or more attributes for the first named file.
3959 This repeats for the second and subsequent files.
3960
3961 This call is intended for programs that want to efficiently
3962 list a directory contents without making many round-trips.
3963 See also C<guestfs_lstatlist> for a similarly efficient call
3964 for getting standard stats.  Very long directory listings
3965 might cause the protocol message size to be exceeded, causing
3966 this call to fail.  The caller must split up such requests
3967 into smaller groups of names.");
3968
3969   ("readlinklist", (RStringList "links", [Pathname "path"; StringList "names"]), 206, [],
3970    [], (* XXX *)
3971    "readlink on multiple files",
3972    "\
3973 This call allows you to do a C<readlink> operation
3974 on multiple files, where all files are in the directory C<path>.
3975 C<names> is the list of files from this directory.
3976
3977 On return you get a list of strings, with a one-to-one
3978 correspondence to the C<names> list.  Each string is the
3979 value of the symbol link.
3980
3981 If the C<readlink(2)> operation fails on any name, then
3982 the corresponding result string is the empty string C<\"\">.
3983 However the whole operation is completed even if there
3984 were C<readlink(2)> errors, and so you can call this
3985 function with names where you don't know if they are
3986 symbolic links already (albeit slightly less efficient).
3987
3988 This call is intended for programs that want to efficiently
3989 list a directory contents without making many round-trips.
3990 Very long directory listings might cause the protocol
3991 message size to be exceeded, causing
3992 this call to fail.  The caller must split up such requests
3993 into smaller groups of names.");
3994
3995   ("pread", (RBufferOut "content", [Pathname "path"; Int "count"; Int64 "offset"]), 207, [ProtocolLimitWarning],
3996    [InitISOFS, Always, TestOutputBuffer (
3997       [["pread"; "/known-4"; "1"; "3"]], "\n");
3998     InitISOFS, Always, TestOutputBuffer (
3999       [["pread"; "/empty"; "0"; "100"]], "")],
4000    "read part of a file",
4001    "\
4002 This command lets you read part of a file.  It reads C<count>
4003 bytes of the file, starting at C<offset>, from file C<path>.
4004
4005 This may read fewer bytes than requested.  For further details
4006 see the L<pread(2)> system call.");
4007
4008   ("part_init", (RErr, [Device "device"; String "parttype"]), 208, [],
4009    [InitEmpty, Always, TestRun (
4010       [["part_init"; "/dev/sda"; "gpt"]])],
4011    "create an empty partition table",
4012    "\
4013 This creates an empty partition table on C<device> of one of the
4014 partition types listed below.  Usually C<parttype> should be
4015 either C<msdos> or C<gpt> (for large disks).
4016
4017 Initially there are no partitions.  Following this, you should
4018 call C<guestfs_part_add> for each partition required.
4019
4020 Possible values for C<parttype> are:
4021
4022 =over 4
4023
4024 =item B<efi> | B<gpt>
4025
4026 Intel EFI / GPT partition table.
4027
4028 This is recommended for >= 2 TB partitions that will be accessed
4029 from Linux and Intel-based Mac OS X.  It also has limited backwards
4030 compatibility with the C<mbr> format.
4031
4032 =item B<mbr> | B<msdos>
4033
4034 The standard PC \"Master Boot Record\" (MBR) format used
4035 by MS-DOS and Windows.  This partition type will B<only> work
4036 for device sizes up to 2 TB.  For large disks we recommend
4037 using C<gpt>.
4038
4039 =back
4040
4041 Other partition table types that may work but are not
4042 supported include:
4043
4044 =over 4
4045
4046 =item B<aix>
4047
4048 AIX disk labels.
4049
4050 =item B<amiga> | B<rdb>
4051
4052 Amiga \"Rigid Disk Block\" format.
4053
4054 =item B<bsd>
4055
4056 BSD disk labels.
4057
4058 =item B<dasd>
4059
4060 DASD, used on IBM mainframes.
4061
4062 =item B<dvh>
4063
4064 MIPS/SGI volumes.
4065
4066 =item B<mac>
4067
4068 Old Mac partition format.  Modern Macs use C<gpt>.
4069
4070 =item B<pc98>
4071
4072 NEC PC-98 format, common in Japan apparently.
4073
4074 =item B<sun>
4075
4076 Sun disk labels.
4077
4078 =back");
4079
4080   ("part_add", (RErr, [Device "device"; String "prlogex"; Int64 "startsect"; Int64 "endsect"]), 209, [],
4081    [InitEmpty, Always, TestRun (
4082       [["part_init"; "/dev/sda"; "mbr"];
4083        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"]]);
4084     InitEmpty, Always, TestRun (
4085       [["part_init"; "/dev/sda"; "gpt"];
4086        ["part_add"; "/dev/sda"; "primary"; "34"; "127"];
4087        ["part_add"; "/dev/sda"; "primary"; "128"; "-34"]]);
4088     InitEmpty, Always, TestRun (
4089       [["part_init"; "/dev/sda"; "mbr"];
4090        ["part_add"; "/dev/sda"; "primary"; "32"; "127"];
4091        ["part_add"; "/dev/sda"; "primary"; "128"; "255"];
4092        ["part_add"; "/dev/sda"; "primary"; "256"; "511"];
4093        ["part_add"; "/dev/sda"; "primary"; "512"; "-1"]])],
4094    "add a partition to the device",
4095    "\
4096 This command adds a partition to C<device>.  If there is no partition
4097 table on the device, call C<guestfs_part_init> first.
4098
4099 The C<prlogex> parameter is the type of partition.  Normally you
4100 should pass C<p> or C<primary> here, but MBR partition tables also
4101 support C<l> (or C<logical>) and C<e> (or C<extended>) partition
4102 types.
4103
4104 C<startsect> and C<endsect> are the start and end of the partition
4105 in I<sectors>.  C<endsect> may be negative, which means it counts
4106 backwards from the end of the disk (C<-1> is the last sector).
4107
4108 Creating a partition which covers the whole disk is not so easy.
4109 Use C<guestfs_part_disk> to do that.");
4110
4111   ("part_disk", (RErr, [Device "device"; String "parttype"]), 210, [DangerWillRobinson],
4112    [InitEmpty, Always, TestRun (
4113       [["part_disk"; "/dev/sda"; "mbr"]]);
4114     InitEmpty, Always, TestRun (
4115       [["part_disk"; "/dev/sda"; "gpt"]])],
4116    "partition whole disk with a single primary partition",
4117    "\
4118 This command is simply a combination of C<guestfs_part_init>
4119 followed by C<guestfs_part_add> to create a single primary partition
4120 covering the whole disk.
4121
4122 C<parttype> is the partition table type, usually C<mbr> or C<gpt>,
4123 but other possible values are described in C<guestfs_part_init>.");
4124
4125   ("part_set_bootable", (RErr, [Device "device"; Int "partnum"; Bool "bootable"]), 211, [],
4126    [InitEmpty, Always, TestRun (
4127       [["part_disk"; "/dev/sda"; "mbr"];
4128        ["part_set_bootable"; "/dev/sda"; "1"; "true"]])],
4129    "make a partition bootable",
4130    "\
4131 This sets the bootable flag on partition numbered C<partnum> on
4132 device C<device>.  Note that partitions are numbered from 1.
4133
4134 The bootable flag is used by some operating systems (notably
4135 Windows) to determine which partition to boot from.  It is by
4136 no means universally recognized.");
4137
4138   ("part_set_name", (RErr, [Device "device"; Int "partnum"; String "name"]), 212, [],
4139    [InitEmpty, Always, TestRun (
4140       [["part_disk"; "/dev/sda"; "gpt"];
4141        ["part_set_name"; "/dev/sda"; "1"; "thepartname"]])],
4142    "set partition name",
4143    "\
4144 This sets the partition name on partition numbered C<partnum> on
4145 device C<device>.  Note that partitions are numbered from 1.
4146
4147 The partition name can only be set on certain types of partition
4148 table.  This works on C<gpt> but not on C<mbr> partitions.");
4149
4150   ("part_list", (RStructList ("partitions", "partition"), [Device "device"]), 213, [],
4151    [], (* XXX Add a regression test for this. *)
4152    "list partitions on a device",
4153    "\
4154 This command parses the partition table on C<device> and
4155 returns the list of partitions found.
4156
4157 The fields in the returned structure are:
4158
4159 =over 4
4160
4161 =item B<part_num>
4162
4163 Partition number, counting from 1.
4164
4165 =item B<part_start>
4166
4167 Start of the partition I<in bytes>.  To get sectors you have to
4168 divide by the device's sector size, see C<guestfs_blockdev_getss>.
4169
4170 =item B<part_end>
4171
4172 End of the partition in bytes.
4173
4174 =item B<part_size>
4175
4176 Size of the partition in bytes.
4177
4178 =back");
4179
4180   ("part_get_parttype", (RString "parttype", [Device "device"]), 214, [],
4181    [InitEmpty, Always, TestOutput (
4182       [["part_disk"; "/dev/sda"; "gpt"];
4183        ["part_get_parttype"; "/dev/sda"]], "gpt")],
4184    "get the partition table type",
4185    "\
4186 This command examines the partition table on C<device> and
4187 returns the partition table type (format) being used.
4188
4189 Common return values include: C<msdos> (a DOS/Windows style MBR
4190 partition table), C<gpt> (a GPT/EFI-style partition table).  Other
4191 values are possible, although unusual.  See C<guestfs_part_init>
4192 for a full list.");
4193
4194   ("fill", (RErr, [Int "c"; Int "len"; Pathname "path"]), 215, [],
4195    [InitBasicFS, Always, TestOutputBuffer (
4196       [["fill"; "0x63"; "10"; "/test"];
4197        ["read_file"; "/test"]], "cccccccccc")],
4198    "fill a file with octets",
4199    "\
4200 This command creates a new file called C<path>.  The initial
4201 content of the file is C<len> octets of C<c>, where C<c>
4202 must be a number in the range C<[0..255]>.
4203
4204 To fill a file with zero bytes (sparsely), it is
4205 much more efficient to use C<guestfs_truncate_size>.");
4206
4207   ("available", (RErr, [StringList "groups"]), 216, [],
4208    [InitNone, Always, TestRun [["available"; ""]]],
4209    "test availability of some parts of the API",
4210    "\
4211 This command is used to check the availability of some
4212 groups of functionality in the appliance, which not all builds of
4213 the libguestfs appliance will be able to provide.
4214
4215 The libguestfs groups, and the functions that those
4216 groups correspond to, are listed in L<guestfs(3)/AVAILABILITY>.
4217
4218 The argument C<groups> is a list of group names, eg:
4219 C<[\"inotify\", \"augeas\"]> would check for the availability of
4220 the Linux inotify functions and Augeas (configuration file
4221 editing) functions.
4222
4223 The command returns no error if I<all> requested groups are available.
4224
4225 It fails with an error if one or more of the requested
4226 groups is unavailable in the appliance.
4227
4228 If an unknown group name is included in the
4229 list of groups then an error is always returned.
4230
4231 I<Notes:>
4232
4233 =over 4
4234
4235 =item *
4236
4237 You must call C<guestfs_launch> before calling this function.
4238
4239 The reason is because we don't know what groups are
4240 supported by the appliance/daemon until it is running and can
4241 be queried.
4242
4243 =item *
4244
4245 If a group of functions is available, this does not necessarily
4246 mean that they will work.  You still have to check for errors
4247 when calling individual API functions even if they are
4248 available.
4249
4250 =item *
4251
4252 It is usually the job of distro packagers to build
4253 complete functionality into the libguestfs appliance.
4254 Upstream libguestfs, if built from source with all
4255 requirements satisfied, will support everything.
4256
4257 =item *
4258
4259 This call was added in version C<1.0.80>.  In previous
4260 versions of libguestfs all you could do would be to speculatively
4261 execute a command to find out if the daemon implemented it.
4262 See also C<guestfs_version>.
4263
4264 =back");
4265
4266   ("dd", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"]), 217, [],
4267    [InitBasicFS, Always, TestOutputBuffer (
4268       [["write_file"; "/src"; "hello, world"; "0"];
4269        ["dd"; "/src"; "/dest"];
4270        ["read_file"; "/dest"]], "hello, world")],
4271    "copy from source to destination using dd",
4272    "\
4273 This command copies from one source device or file C<src>
4274 to another destination device or file C<dest>.  Normally you
4275 would use this to copy to or from a device or partition, for
4276 example to duplicate a filesystem.
4277
4278 If the destination is a device, it must be as large or larger
4279 than the source file or device, otherwise the copy will fail.
4280 This command cannot do partial copies (see C<guestfs_copy_size>).");
4281
4282   ("filesize", (RInt64 "size", [Pathname "file"]), 218, [],
4283    [InitBasicFS, Always, TestOutputInt (
4284       [["write_file"; "/file"; "hello, world"; "0"];
4285        ["filesize"; "/file"]], 12)],
4286    "return the size of the file in bytes",
4287    "\
4288 This command returns the size of C<file> in bytes.
4289
4290 To get other stats about a file, use C<guestfs_stat>, C<guestfs_lstat>,
4291 C<guestfs_is_dir>, C<guestfs_is_file> etc.
4292 To get the size of block devices, use C<guestfs_blockdev_getsize64>.");
4293
4294   ("lvrename", (RErr, [String "logvol"; String "newlogvol"]), 219, [],
4295    [InitBasicFSonLVM, Always, TestOutputList (
4296       [["lvrename"; "/dev/VG/LV"; "/dev/VG/LV2"];
4297        ["lvs"]], ["/dev/VG/LV2"])],
4298    "rename an LVM logical volume",
4299    "\
4300 Rename a logical volume C<logvol> with the new name C<newlogvol>.");
4301
4302   ("vgrename", (RErr, [String "volgroup"; String "newvolgroup"]), 220, [],
4303    [InitBasicFSonLVM, Always, TestOutputList (
4304       [["umount"; "/"];
4305        ["vg_activate"; "false"; "VG"];
4306        ["vgrename"; "VG"; "VG2"];
4307        ["vg_activate"; "true"; "VG2"];
4308        ["mount_options"; ""; "/dev/VG2/LV"; "/"];
4309        ["vgs"]], ["VG2"])],
4310    "rename an LVM volume group",
4311    "\
4312 Rename a volume group C<volgroup> with the new name C<newvolgroup>.");
4313
4314   ("initrd_cat", (RBufferOut "content", [Pathname "initrdpath"; String "filename"]), 221, [ProtocolLimitWarning],
4315    [InitISOFS, Always, TestOutputBuffer (
4316       [["initrd_cat"; "/initrd"; "known-4"]], "abc\ndef\nghi")],
4317    "list the contents of a single file in an initrd",
4318    "\
4319 This command unpacks the file C<filename> from the initrd file
4320 called C<initrdpath>.  The filename must be given I<without> the
4321 initial C</> character.
4322
4323 For example, in guestfish you could use the following command
4324 to examine the boot script (usually called C</init>)
4325 contained in a Linux initrd or initramfs image:
4326
4327  initrd-cat /boot/initrd-<version>.img init
4328
4329 See also C<guestfs_initrd_list>.");
4330
4331   ("pvuuid", (RString "uuid", [Device "device"]), 222, [],
4332    [],
4333    "get the UUID of a physical volume",
4334    "\
4335 This command returns the UUID of the LVM PV C<device>.");
4336
4337   ("vguuid", (RString "uuid", [String "vgname"]), 223, [],
4338    [],
4339    "get the UUID of a volume group",
4340    "\
4341 This command returns the UUID of the LVM VG named C<vgname>.");
4342
4343   ("lvuuid", (RString "uuid", [Device "device"]), 224, [],
4344    [],
4345    "get the UUID of a logical volume",
4346    "\
4347 This command returns the UUID of the LVM LV C<device>.");
4348
4349   ("vgpvuuids", (RStringList "uuids", [String "vgname"]), 225, [],
4350    [],
4351    "get the PV UUIDs containing the volume group",
4352    "\
4353 Given a VG called C<vgname>, this returns the UUIDs of all
4354 the physical volumes that this volume group resides on.
4355
4356 You can use this along with C<guestfs_pvs> and C<guestfs_pvuuid>
4357 calls to associate physical volumes and volume groups.
4358
4359 See also C<guestfs_vglvuuids>.");
4360
4361   ("vglvuuids", (RStringList "uuids", [String "vgname"]), 226, [],
4362    [],
4363    "get the LV UUIDs of all LVs in the volume group",
4364    "\
4365 Given a VG called C<vgname>, this returns the UUIDs of all
4366 the logical volumes created in this volume group.
4367
4368 You can use this along with C<guestfs_lvs> and C<guestfs_lvuuid>
4369 calls to associate logical volumes and volume groups.
4370
4371 See also C<guestfs_vgpvuuids>.");
4372
4373   ("copy_size", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"; Int64 "size"]), 227, [],
4374    [InitBasicFS, Always, TestOutputBuffer (
4375       [["write_file"; "/src"; "hello, world"; "0"];
4376        ["copy_size"; "/src"; "/dest"; "5"];
4377        ["read_file"; "/dest"]], "hello")],
4378    "copy size bytes from source to destination using dd",
4379    "\
4380 This command copies exactly C<size> bytes from one source device
4381 or file C<src> to another destination device or file C<dest>.
4382
4383 Note this will fail if the source is too short or if the destination
4384 is not large enough.");
4385
4386   ("zero_device", (RErr, [Device "device"]), 228, [DangerWillRobinson],
4387    [InitBasicFSonLVM, Always, TestRun (
4388       [["zero_device"; "/dev/VG/LV"]])],
4389    "write zeroes to an entire device",
4390    "\
4391 This command writes zeroes over the entire C<device>.  Compare
4392 with C<guestfs_zero> which just zeroes the first few blocks of
4393 a device.");
4394
4395   ("txz_in", (RErr, [FileIn "tarball"; Pathname "directory"]), 229, [],
4396    [InitBasicFS, Always, TestOutput (
4397       [["txz_in"; "../images/helloworld.tar.xz"; "/"];
4398        ["cat"; "/hello"]], "hello\n")],
4399    "unpack compressed tarball to directory",
4400    "\
4401 This command uploads and unpacks local file C<tarball> (an
4402 I<xz compressed> tar file) into C<directory>.");
4403
4404   ("txz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 230, [],
4405    [],
4406    "pack directory into compressed tarball",
4407    "\
4408 This command packs the contents of C<directory> and downloads
4409 it to local file C<tarball> (as an xz compressed tar archive).");
4410
4411   ("ntfsresize", (RErr, [Device "device"]), 231, [Optional "ntfsprogs"],
4412    [],
4413    "resize an NTFS filesystem",
4414    "\
4415 This command resizes an NTFS filesystem, expanding or
4416 shrinking it to the size of the underlying device.
4417 See also L<ntfsresize(8)>.");
4418
4419   ("vgscan", (RErr, []), 232, [],
4420    [InitEmpty, Always, TestRun (
4421       [["vgscan"]])],
4422    "rescan for LVM physical volumes, volume groups and logical volumes",
4423    "\
4424 This rescans all block devices and rebuilds the list of LVM
4425 physical volumes, volume groups and logical volumes.");
4426
4427   ("part_del", (RErr, [Device "device"; Int "partnum"]), 233, [],
4428    [InitEmpty, Always, TestRun (
4429       [["part_init"; "/dev/sda"; "mbr"];
4430        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4431        ["part_del"; "/dev/sda"; "1"]])],
4432    "delete a partition",
4433    "\
4434 This command deletes the partition numbered C<partnum> on C<device>.
4435
4436 Note that in the case of MBR partitioning, deleting an
4437 extended partition also deletes any logical partitions
4438 it contains.");
4439
4440   ("part_get_bootable", (RBool "bootable", [Device "device"; Int "partnum"]), 234, [],
4441    [InitEmpty, Always, TestOutputTrue (
4442       [["part_init"; "/dev/sda"; "mbr"];
4443        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4444        ["part_set_bootable"; "/dev/sda"; "1"; "true"];
4445        ["part_get_bootable"; "/dev/sda"; "1"]])],
4446    "return true if a partition is bootable",
4447    "\
4448 This command returns true if the partition C<partnum> on
4449 C<device> has the bootable flag set.
4450
4451 See also C<guestfs_part_set_bootable>.");
4452
4453   ("part_get_mbr_id", (RInt "idbyte", [Device "device"; Int "partnum"]), 235, [FishOutput FishOutputHexadecimal],
4454    [InitEmpty, Always, TestOutputInt (
4455       [["part_init"; "/dev/sda"; "mbr"];
4456        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4457        ["part_set_mbr_id"; "/dev/sda"; "1"; "0x7f"];
4458        ["part_get_mbr_id"; "/dev/sda"; "1"]], 0x7f)],
4459    "get the MBR type byte (ID byte) from a partition",
4460    "\
4461 Returns the MBR type byte (also known as the ID byte) from
4462 the numbered partition C<partnum>.
4463
4464 Note that only MBR (old DOS-style) partitions have type bytes.
4465 You will get undefined results for other partition table
4466 types (see C<guestfs_part_get_parttype>).");
4467
4468   ("part_set_mbr_id", (RErr, [Device "device"; Int "partnum"; Int "idbyte"]), 236, [],
4469    [], (* tested by part_get_mbr_id *)
4470    "set the MBR type byte (ID byte) of a partition",
4471    "\
4472 Sets the MBR type byte (also known as the ID byte) of
4473 the numbered partition C<partnum> to C<idbyte>.  Note
4474 that the type bytes quoted in most documentation are
4475 in fact hexadecimal numbers, but usually documented
4476 without any leading \"0x\" which might be confusing.
4477
4478 Note that only MBR (old DOS-style) partitions have type bytes.
4479 You will get undefined results for other partition table
4480 types (see C<guestfs_part_get_parttype>).");
4481
4482   ("checksum_device", (RString "checksum", [String "csumtype"; Device "device"]), 237, [],
4483    [InitISOFS, Always, TestOutput (
4484       [["checksum_device"; "md5"; "/dev/sdd"]],
4485       (Digest.to_hex (Digest.file "images/test.iso")))],
4486    "compute MD5, SHAx or CRC checksum of the contents of a device",
4487    "\
4488 This call computes the MD5, SHAx or CRC checksum of the
4489 contents of the device named C<device>.  For the types of
4490 checksums supported see the C<guestfs_checksum> command.");
4491
4492   ("lvresize_free", (RErr, [Device "lv"; Int "percent"]), 238, [Optional "lvm2"],
4493    [InitNone, Always, TestRun (
4494       [["part_disk"; "/dev/sda"; "mbr"];
4495        ["pvcreate"; "/dev/sda1"];
4496        ["vgcreate"; "VG"; "/dev/sda1"];
4497        ["lvcreate"; "LV"; "VG"; "10"];
4498        ["lvresize_free"; "/dev/VG/LV"; "100"]])],
4499    "expand an LV to fill free space",
4500    "\
4501 This expands an existing logical volume C<lv> so that it fills
4502 C<pc>% of the remaining free space in the volume group.  Commonly
4503 you would call this with pc = 100 which expands the logical volume
4504 as much as possible, using all remaining free space in the volume
4505 group.");
4506
4507   ("aug_clear", (RErr, [String "augpath"]), 239, [Optional "augeas"],
4508    [], (* XXX Augeas code needs tests. *)
4509    "clear Augeas path",
4510    "\
4511 Set the value associated with C<path> to C<NULL>.  This
4512 is the same as the L<augtool(1)> C<clear> command.");
4513
4514   ("get_umask", (RInt "mask", []), 240, [FishOutput FishOutputOctal],
4515    [InitEmpty, Always, TestOutputInt (
4516       [["get_umask"]], 0o22)],
4517    "get the current umask",
4518    "\
4519 Return the current umask.  By default the umask is C<022>
4520 unless it has been set by calling C<guestfs_umask>.");
4521
4522   ("debug_upload", (RErr, [FileIn "filename"; String "tmpname"; Int "mode"]), 241, [],
4523    [],
4524    "upload a file to the appliance (internal use only)",
4525    "\
4526 The C<guestfs_debug_upload> command uploads a file to
4527 the libguestfs appliance.
4528
4529 There is no comprehensive help for this command.  You have
4530 to look at the file C<daemon/debug.c> in the libguestfs source
4531 to find out what it is for.");
4532
4533   ("base64_in", (RErr, [FileIn "base64file"; Pathname "filename"]), 242, [],
4534    [InitBasicFS, Always, TestOutput (
4535       [["base64_in"; "../images/hello.b64"; "/hello"];
4536        ["cat"; "/hello"]], "hello\n")],
4537    "upload base64-encoded data to file",
4538    "\
4539 This command uploads base64-encoded data from C<base64file>
4540 to C<filename>.");
4541
4542   ("base64_out", (RErr, [Pathname "filename"; FileOut "base64file"]), 243, [],
4543    [],
4544    "download file and encode as base64",
4545    "\
4546 This command downloads the contents of C<filename>, writing
4547 it out to local file C<base64file> encoded as base64.");
4548
4549 ]
4550
4551 let all_functions = non_daemon_functions @ daemon_functions
4552
4553 (* In some places we want the functions to be displayed sorted
4554  * alphabetically, so this is useful:
4555  *)
4556 let all_functions_sorted =
4557   List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
4558                compare n1 n2) all_functions
4559
4560 (* Field types for structures. *)
4561 type field =
4562   | FChar                       (* C 'char' (really, a 7 bit byte). *)
4563   | FString                     (* nul-terminated ASCII string, NOT NULL. *)
4564   | FBuffer                     (* opaque buffer of bytes, (char *, int) pair *)
4565   | FUInt32
4566   | FInt32
4567   | FUInt64
4568   | FInt64
4569   | FBytes                      (* Any int measure that counts bytes. *)
4570   | FUUID                       (* 32 bytes long, NOT nul-terminated. *)
4571   | FOptPercent                 (* [0..100], or -1 meaning "not present". *)
4572
4573 (* Because we generate extra parsing code for LVM command line tools,
4574  * we have to pull out the LVM columns separately here.
4575  *)
4576 let lvm_pv_cols = [
4577   "pv_name", FString;
4578   "pv_uuid", FUUID;
4579   "pv_fmt", FString;
4580   "pv_size", FBytes;
4581   "dev_size", FBytes;
4582   "pv_free", FBytes;
4583   "pv_used", FBytes;
4584   "pv_attr", FString (* XXX *);
4585   "pv_pe_count", FInt64;
4586   "pv_pe_alloc_count", FInt64;
4587   "pv_tags", FString;
4588   "pe_start", FBytes;
4589   "pv_mda_count", FInt64;
4590   "pv_mda_free", FBytes;
4591   (* Not in Fedora 10:
4592      "pv_mda_size", FBytes;
4593   *)
4594 ]
4595 let lvm_vg_cols = [
4596   "vg_name", FString;
4597   "vg_uuid", FUUID;
4598   "vg_fmt", FString;
4599   "vg_attr", FString (* XXX *);
4600   "vg_size", FBytes;
4601   "vg_free", FBytes;
4602   "vg_sysid", FString;
4603   "vg_extent_size", FBytes;
4604   "vg_extent_count", FInt64;
4605   "vg_free_count", FInt64;
4606   "max_lv", FInt64;
4607   "max_pv", FInt64;
4608   "pv_count", FInt64;
4609   "lv_count", FInt64;
4610   "snap_count", FInt64;
4611   "vg_seqno", FInt64;
4612   "vg_tags", FString;
4613   "vg_mda_count", FInt64;
4614   "vg_mda_free", FBytes;
4615   (* Not in Fedora 10:
4616      "vg_mda_size", FBytes;
4617   *)
4618 ]
4619 let lvm_lv_cols = [
4620   "lv_name", FString;
4621   "lv_uuid", FUUID;
4622   "lv_attr", FString (* XXX *);
4623   "lv_major", FInt64;
4624   "lv_minor", FInt64;
4625   "lv_kernel_major", FInt64;
4626   "lv_kernel_minor", FInt64;
4627   "lv_size", FBytes;
4628   "seg_count", FInt64;
4629   "origin", FString;
4630   "snap_percent", FOptPercent;
4631   "copy_percent", FOptPercent;
4632   "move_pv", FString;
4633   "lv_tags", FString;
4634   "mirror_log", FString;
4635   "modules", FString;
4636 ]
4637
4638 (* Names and fields in all structures (in RStruct and RStructList)
4639  * that we support.
4640  *)
4641 let structs = [
4642   (* The old RIntBool return type, only ever used for aug_defnode.  Do
4643    * not use this struct in any new code.
4644    *)
4645   "int_bool", [
4646     "i", FInt32;                (* for historical compatibility *)
4647     "b", FInt32;                (* for historical compatibility *)
4648   ];
4649
4650   (* LVM PVs, VGs, LVs. *)
4651   "lvm_pv", lvm_pv_cols;
4652   "lvm_vg", lvm_vg_cols;
4653   "lvm_lv", lvm_lv_cols;
4654
4655   (* Column names and types from stat structures.
4656    * NB. Can't use things like 'st_atime' because glibc header files
4657    * define some of these as macros.  Ugh.
4658    *)
4659   "stat", [
4660     "dev", FInt64;
4661     "ino", FInt64;
4662     "mode", FInt64;
4663     "nlink", FInt64;
4664     "uid", FInt64;
4665     "gid", FInt64;
4666     "rdev", FInt64;
4667     "size", FInt64;
4668     "blksize", FInt64;
4669     "blocks", FInt64;
4670     "atime", FInt64;
4671     "mtime", FInt64;
4672     "ctime", FInt64;
4673   ];
4674   "statvfs", [
4675     "bsize", FInt64;
4676     "frsize", FInt64;
4677     "blocks", FInt64;
4678     "bfree", FInt64;
4679     "bavail", FInt64;
4680     "files", FInt64;
4681     "ffree", FInt64;
4682     "favail", FInt64;
4683     "fsid", FInt64;
4684     "flag", FInt64;
4685     "namemax", FInt64;
4686   ];
4687
4688   (* Column names in dirent structure. *)
4689   "dirent", [
4690     "ino", FInt64;
4691     (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
4692     "ftyp", FChar;
4693     "name", FString;
4694   ];
4695
4696   (* Version numbers. *)
4697   "version", [
4698     "major", FInt64;
4699     "minor", FInt64;
4700     "release", FInt64;
4701     "extra", FString;
4702   ];
4703
4704   (* Extended attribute. *)
4705   "xattr", [
4706     "attrname", FString;
4707     "attrval", FBuffer;
4708   ];
4709
4710   (* Inotify events. *)
4711   "inotify_event", [
4712     "in_wd", FInt64;
4713     "in_mask", FUInt32;
4714     "in_cookie", FUInt32;
4715     "in_name", FString;
4716   ];
4717
4718   (* Partition table entry. *)
4719   "partition", [
4720     "part_num", FInt32;
4721     "part_start", FBytes;
4722     "part_end", FBytes;
4723     "part_size", FBytes;
4724   ];
4725 ] (* end of structs *)
4726
4727 (* Ugh, Java has to be different ..
4728  * These names are also used by the Haskell bindings.
4729  *)
4730 let java_structs = [
4731   "int_bool", "IntBool";
4732   "lvm_pv", "PV";
4733   "lvm_vg", "VG";
4734   "lvm_lv", "LV";
4735   "stat", "Stat";
4736   "statvfs", "StatVFS";
4737   "dirent", "Dirent";
4738   "version", "Version";
4739   "xattr", "XAttr";
4740   "inotify_event", "INotifyEvent";
4741   "partition", "Partition";
4742 ]
4743
4744 (* What structs are actually returned. *)
4745 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
4746
4747 (* Returns a list of RStruct/RStructList structs that are returned
4748  * by any function.  Each element of returned list is a pair:
4749  *
4750  * (structname, RStructOnly)
4751  *    == there exists function which returns RStruct (_, structname)
4752  * (structname, RStructListOnly)
4753  *    == there exists function which returns RStructList (_, structname)
4754  * (structname, RStructAndList)
4755  *    == there are functions returning both RStruct (_, structname)
4756  *                                      and RStructList (_, structname)
4757  *)
4758 let rstructs_used_by functions =
4759   (* ||| is a "logical OR" for rstructs_used_t *)
4760   let (|||) a b =
4761     match a, b with
4762     | RStructAndList, _
4763     | _, RStructAndList -> RStructAndList
4764     | RStructOnly, RStructListOnly
4765     | RStructListOnly, RStructOnly -> RStructAndList
4766     | RStructOnly, RStructOnly -> RStructOnly
4767     | RStructListOnly, RStructListOnly -> RStructListOnly
4768   in
4769
4770   let h = Hashtbl.create 13 in
4771
4772   (* if elem->oldv exists, update entry using ||| operator,
4773    * else just add elem->newv to the hash
4774    *)
4775   let update elem newv =
4776     try  let oldv = Hashtbl.find h elem in
4777          Hashtbl.replace h elem (newv ||| oldv)
4778     with Not_found -> Hashtbl.add h elem newv
4779   in
4780
4781   List.iter (
4782     fun (_, style, _, _, _, _, _) ->
4783       match fst style with
4784       | RStruct (_, structname) -> update structname RStructOnly
4785       | RStructList (_, structname) -> update structname RStructListOnly
4786       | _ -> ()
4787   ) functions;
4788
4789   (* return key->values as a list of (key,value) *)
4790   Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
4791
4792 (* Used for testing language bindings. *)
4793 type callt =
4794   | CallString of string
4795   | CallOptString of string option
4796   | CallStringList of string list
4797   | CallInt of int
4798   | CallInt64 of int64
4799   | CallBool of bool
4800
4801 (* Used to memoize the result of pod2text. *)
4802 let pod2text_memo_filename = "src/.pod2text.data"
4803 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
4804   try
4805     let chan = open_in pod2text_memo_filename in
4806     let v = input_value chan in
4807     close_in chan;
4808     v
4809   with
4810     _ -> Hashtbl.create 13
4811 let pod2text_memo_updated () =
4812   let chan = open_out pod2text_memo_filename in
4813   output_value chan pod2text_memo;
4814   close_out chan
4815
4816 (* Useful functions.
4817  * Note we don't want to use any external OCaml libraries which
4818  * makes this a bit harder than it should be.
4819  *)
4820 module StringMap = Map.Make (String)
4821
4822 let failwithf fs = ksprintf failwith fs
4823
4824 let unique = let i = ref 0 in fun () -> incr i; !i
4825
4826 let replace_char s c1 c2 =
4827   let s2 = String.copy s in
4828   let r = ref false in
4829   for i = 0 to String.length s2 - 1 do
4830     if String.unsafe_get s2 i = c1 then (
4831       String.unsafe_set s2 i c2;
4832       r := true
4833     )
4834   done;
4835   if not !r then s else s2
4836
4837 let isspace c =
4838   c = ' '
4839   (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
4840
4841 let triml ?(test = isspace) str =
4842   let i = ref 0 in
4843   let n = ref (String.length str) in
4844   while !n > 0 && test str.[!i]; do
4845     decr n;
4846     incr i
4847   done;
4848   if !i = 0 then str
4849   else String.sub str !i !n
4850
4851 let trimr ?(test = isspace) str =
4852   let n = ref (String.length str) in
4853   while !n > 0 && test str.[!n-1]; do
4854     decr n
4855   done;
4856   if !n = String.length str then str
4857   else String.sub str 0 !n
4858
4859 let trim ?(test = isspace) str =
4860   trimr ~test (triml ~test str)
4861
4862 let rec find s sub =
4863   let len = String.length s in
4864   let sublen = String.length sub in
4865   let rec loop i =
4866     if i <= len-sublen then (
4867       let rec loop2 j =
4868         if j < sublen then (
4869           if s.[i+j] = sub.[j] then loop2 (j+1)
4870           else -1
4871         ) else
4872           i (* found *)
4873       in
4874       let r = loop2 0 in
4875       if r = -1 then loop (i+1) else r
4876     ) else
4877       -1 (* not found *)
4878   in
4879   loop 0
4880
4881 let rec replace_str s s1 s2 =
4882   let len = String.length s in
4883   let sublen = String.length s1 in
4884   let i = find s s1 in
4885   if i = -1 then s
4886   else (
4887     let s' = String.sub s 0 i in
4888     let s'' = String.sub s (i+sublen) (len-i-sublen) in
4889     s' ^ s2 ^ replace_str s'' s1 s2
4890   )
4891
4892 let rec string_split sep str =
4893   let len = String.length str in
4894   let seplen = String.length sep in
4895   let i = find str sep in
4896   if i = -1 then [str]
4897   else (
4898     let s' = String.sub str 0 i in
4899     let s'' = String.sub str (i+seplen) (len-i-seplen) in
4900     s' :: string_split sep s''
4901   )
4902
4903 let files_equal n1 n2 =
4904   let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
4905   match Sys.command cmd with
4906   | 0 -> true
4907   | 1 -> false
4908   | i -> failwithf "%s: failed with error code %d" cmd i
4909
4910 let rec filter_map f = function
4911   | [] -> []
4912   | x :: xs ->
4913       match f x with
4914       | Some y -> y :: filter_map f xs
4915       | None -> filter_map f xs
4916
4917 let rec find_map f = function
4918   | [] -> raise Not_found
4919   | x :: xs ->
4920       match f x with
4921       | Some y -> y
4922       | None -> find_map f xs
4923
4924 let iteri f xs =
4925   let rec loop i = function
4926     | [] -> ()
4927     | x :: xs -> f i x; loop (i+1) xs
4928   in
4929   loop 0 xs
4930
4931 let mapi f xs =
4932   let rec loop i = function
4933     | [] -> []
4934     | x :: xs -> let r = f i x in r :: loop (i+1) xs
4935   in
4936   loop 0 xs
4937
4938 let count_chars c str =
4939   let count = ref 0 in
4940   for i = 0 to String.length str - 1 do
4941     if c = String.unsafe_get str i then incr count
4942   done;
4943   !count
4944
4945 let name_of_argt = function
4946   | Pathname n | Device n | Dev_or_Path n | String n | OptString n
4947   | StringList n | DeviceList n | Bool n | Int n | Int64 n
4948   | FileIn n | FileOut n -> n
4949
4950 let java_name_of_struct typ =
4951   try List.assoc typ java_structs
4952   with Not_found ->
4953     failwithf
4954       "java_name_of_struct: no java_structs entry corresponding to %s" typ
4955
4956 let cols_of_struct typ =
4957   try List.assoc typ structs
4958   with Not_found ->
4959     failwithf "cols_of_struct: unknown struct %s" typ
4960
4961 let seq_of_test = function
4962   | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
4963   | TestOutputListOfDevices (s, _)
4964   | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
4965   | TestOutputTrue s | TestOutputFalse s
4966   | TestOutputLength (s, _) | TestOutputBuffer (s, _)
4967   | TestOutputStruct (s, _)
4968   | TestLastFail s -> s
4969
4970 (* Handling for function flags. *)
4971 let protocol_limit_warning =
4972   "Because of the message protocol, there is a transfer limit
4973 of somewhere between 2MB and 4MB.  See L<guestfs(3)/PROTOCOL LIMITS>."
4974
4975 let danger_will_robinson =
4976   "B<This command is dangerous.  Without careful use you
4977 can easily destroy all your data>."
4978
4979 let deprecation_notice flags =
4980   try
4981     let alt =
4982       find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
4983     let txt =
4984       sprintf "This function is deprecated.
4985 In new code, use the C<%s> call instead.
4986
4987 Deprecated functions will not be removed from the API, but the
4988 fact that they are deprecated indicates that there are problems
4989 with correct use of these functions." alt in
4990     Some txt
4991   with
4992     Not_found -> None
4993
4994 (* Create list of optional groups. *)
4995 let optgroups =
4996   let h = Hashtbl.create 13 in
4997   List.iter (
4998     fun (name, _, _, flags, _, _, _) ->
4999       List.iter (
5000         function
5001         | Optional group ->
5002             let names = try Hashtbl.find h group with Not_found -> [] in
5003             Hashtbl.replace h group (name :: names)
5004         | _ -> ()
5005       ) flags
5006   ) daemon_functions;
5007   let groups = Hashtbl.fold (fun k _ ks -> k :: ks) h [] in
5008   let groups =
5009     List.map (
5010       fun group -> group, List.sort compare (Hashtbl.find h group)
5011     ) groups in
5012   List.sort (fun x y -> compare (fst x) (fst y)) groups
5013
5014 (* Check function names etc. for consistency. *)
5015 let check_functions () =
5016   let contains_uppercase str =
5017     let len = String.length str in
5018     let rec loop i =
5019       if i >= len then false
5020       else (
5021         let c = str.[i] in
5022         if c >= 'A' && c <= 'Z' then true
5023         else loop (i+1)
5024       )
5025     in
5026     loop 0
5027   in
5028
5029   (* Check function names. *)
5030   List.iter (
5031     fun (name, _, _, _, _, _, _) ->
5032       if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
5033         failwithf "function name %s does not need 'guestfs' prefix" name;
5034       if name = "" then
5035         failwithf "function name is empty";
5036       if name.[0] < 'a' || name.[0] > 'z' then
5037         failwithf "function name %s must start with lowercase a-z" name;
5038       if String.contains name '-' then
5039         failwithf "function name %s should not contain '-', use '_' instead."
5040           name
5041   ) all_functions;
5042
5043   (* Check function parameter/return names. *)
5044   List.iter (
5045     fun (name, style, _, _, _, _, _) ->
5046       let check_arg_ret_name n =
5047         if contains_uppercase n then
5048           failwithf "%s param/ret %s should not contain uppercase chars"
5049             name n;
5050         if String.contains n '-' || String.contains n '_' then
5051           failwithf "%s param/ret %s should not contain '-' or '_'"
5052             name n;
5053         if n = "value" then
5054           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;
5055         if n = "int" || n = "char" || n = "short" || n = "long" then
5056           failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
5057         if n = "i" || n = "n" then
5058           failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
5059         if n = "argv" || n = "args" then
5060           failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
5061
5062         (* List Haskell, OCaml and C keywords here.
5063          * http://www.haskell.org/haskellwiki/Keywords
5064          * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
5065          * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
5066          * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
5067          *   |perl -pe 's/(.+)/"$1";/'|fmt -70
5068          * Omitting _-containing words, since they're handled above.
5069          * Omitting the OCaml reserved word, "val", is ok,
5070          * and saves us from renaming several parameters.
5071          *)
5072         let reserved = [
5073           "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
5074           "char"; "class"; "const"; "constraint"; "continue"; "data";
5075           "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
5076           "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
5077           "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
5078           "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
5079           "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
5080           "interface";
5081           "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
5082           "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
5083           "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
5084           "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
5085           "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
5086           "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
5087           "volatile"; "when"; "where"; "while";
5088           ] in
5089         if List.mem n reserved then
5090           failwithf "%s has param/ret using reserved word %s" name n;
5091       in
5092
5093       (match fst style with
5094        | RErr -> ()
5095        | RInt n | RInt64 n | RBool n
5096        | RConstString n | RConstOptString n | RString n
5097        | RStringList n | RStruct (n, _) | RStructList (n, _)
5098        | RHashtable n | RBufferOut n ->
5099            check_arg_ret_name n
5100       );
5101       List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
5102   ) all_functions;
5103
5104   (* Check short descriptions. *)
5105   List.iter (
5106     fun (name, _, _, _, _, shortdesc, _) ->
5107       if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
5108         failwithf "short description of %s should begin with lowercase." name;
5109       let c = shortdesc.[String.length shortdesc-1] in
5110       if c = '\n' || c = '.' then
5111         failwithf "short description of %s should not end with . or \\n." name
5112   ) all_functions;
5113
5114   (* Check long descriptions. *)
5115   List.iter (
5116     fun (name, _, _, _, _, _, longdesc) ->
5117       if longdesc.[String.length longdesc-1] = '\n' then
5118         failwithf "long description of %s should not end with \\n." name
5119   ) all_functions;
5120
5121   (* Check proc_nrs. *)
5122   List.iter (
5123     fun (name, _, proc_nr, _, _, _, _) ->
5124       if proc_nr <= 0 then
5125         failwithf "daemon function %s should have proc_nr > 0" name
5126   ) daemon_functions;
5127
5128   List.iter (
5129     fun (name, _, proc_nr, _, _, _, _) ->
5130       if proc_nr <> -1 then
5131         failwithf "non-daemon function %s should have proc_nr -1" name
5132   ) non_daemon_functions;
5133
5134   let proc_nrs =
5135     List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
5136       daemon_functions in
5137   let proc_nrs =
5138     List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
5139   let rec loop = function
5140     | [] -> ()
5141     | [_] -> ()
5142     | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
5143         loop rest
5144     | (name1,nr1) :: (name2,nr2) :: _ ->
5145         failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
5146           name1 name2 nr1 nr2
5147   in
5148   loop proc_nrs;
5149
5150   (* Check tests. *)
5151   List.iter (
5152     function
5153       (* Ignore functions that have no tests.  We generate a
5154        * warning when the user does 'make check' instead.
5155        *)
5156     | name, _, _, _, [], _, _ -> ()
5157     | name, _, _, _, tests, _, _ ->
5158         let funcs =
5159           List.map (
5160             fun (_, _, test) ->
5161               match seq_of_test test with
5162               | [] ->
5163                   failwithf "%s has a test containing an empty sequence" name
5164               | cmds -> List.map List.hd cmds
5165           ) tests in
5166         let funcs = List.flatten funcs in
5167
5168         let tested = List.mem name funcs in
5169
5170         if not tested then
5171           failwithf "function %s has tests but does not test itself" name
5172   ) all_functions
5173
5174 (* 'pr' prints to the current output file. *)
5175 let chan = ref Pervasives.stdout
5176 let lines = ref 0
5177 let pr fs =
5178   ksprintf
5179     (fun str ->
5180        let i = count_chars '\n' str in
5181        lines := !lines + i;
5182        output_string !chan str
5183     ) fs
5184
5185 let copyright_years =
5186   let this_year = 1900 + (localtime (time ())).tm_year in
5187   if this_year > 2009 then sprintf "2009-%04d" this_year else "2009"
5188
5189 (* Generate a header block in a number of standard styles. *)
5190 type comment_style =
5191     CStyle | CPlusPlusStyle | HashStyle | OCamlStyle | HaskellStyle
5192 type license = GPLv2plus | LGPLv2plus
5193
5194 let generate_header ?(extra_inputs = []) comment license =
5195   let inputs = "src/generator.ml" :: extra_inputs in
5196   let c = match comment with
5197     | CStyle ->         pr "/* "; " *"
5198     | CPlusPlusStyle -> pr "// "; "//"
5199     | HashStyle ->      pr "# ";  "#"
5200     | OCamlStyle ->     pr "(* "; " *"
5201     | HaskellStyle ->   pr "{- "; "  " in
5202   pr "libguestfs generated file\n";
5203   pr "%s WARNING: THIS FILE IS GENERATED FROM:\n" c;
5204   List.iter (pr "%s   %s\n" c) inputs;
5205   pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
5206   pr "%s\n" c;
5207   pr "%s Copyright (C) %s Red Hat Inc.\n" c copyright_years;
5208   pr "%s\n" c;
5209   (match license with
5210    | GPLv2plus ->
5211        pr "%s This program is free software; you can redistribute it and/or modify\n" c;
5212        pr "%s it under the terms of the GNU General Public License as published by\n" c;
5213        pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
5214        pr "%s (at your option) any later version.\n" c;
5215        pr "%s\n" c;
5216        pr "%s This program is distributed in the hope that it will be useful,\n" c;
5217        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5218        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n" c;
5219        pr "%s GNU General Public License for more details.\n" c;
5220        pr "%s\n" c;
5221        pr "%s You should have received a copy of the GNU General Public License along\n" c;
5222        pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
5223        pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
5224
5225    | LGPLv2plus ->
5226        pr "%s This library is free software; you can redistribute it and/or\n" c;
5227        pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
5228        pr "%s License as published by the Free Software Foundation; either\n" c;
5229        pr "%s version 2 of the License, or (at your option) any later version.\n" c;
5230        pr "%s\n" c;
5231        pr "%s This library is distributed in the hope that it will be useful,\n" c;
5232        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5233        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n" c;
5234        pr "%s Lesser General Public License for more details.\n" c;
5235        pr "%s\n" c;
5236        pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
5237        pr "%s License along with this library; if not, write to the Free Software\n" c;
5238        pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
5239   );
5240   (match comment with
5241    | CStyle -> pr " */\n"
5242    | CPlusPlusStyle
5243    | HashStyle -> ()
5244    | OCamlStyle -> pr " *)\n"
5245    | HaskellStyle -> pr "-}\n"
5246   );
5247   pr "\n"
5248
5249 (* Start of main code generation functions below this line. *)
5250
5251 (* Generate the pod documentation for the C API. *)
5252 let rec generate_actions_pod () =
5253   List.iter (
5254     fun (shortname, style, _, flags, _, _, longdesc) ->
5255       if not (List.mem NotInDocs flags) then (
5256         let name = "guestfs_" ^ shortname in
5257         pr "=head2 %s\n\n" name;
5258         pr " ";
5259         generate_prototype ~extern:false ~handle:"g" name style;
5260         pr "\n\n";
5261         pr "%s\n\n" longdesc;
5262         (match fst style with
5263          | RErr ->
5264              pr "This function returns 0 on success or -1 on error.\n\n"
5265          | RInt _ ->
5266              pr "On error this function returns -1.\n\n"
5267          | RInt64 _ ->
5268              pr "On error this function returns -1.\n\n"
5269          | RBool _ ->
5270              pr "This function returns a C truth value on success or -1 on error.\n\n"
5271          | RConstString _ ->
5272              pr "This function returns a string, or NULL on error.
5273 The string is owned by the guest handle and must I<not> be freed.\n\n"
5274          | RConstOptString _ ->
5275              pr "This function returns a string which may be NULL.
5276 There is way to return an error from this function.
5277 The string is owned by the guest handle and must I<not> be freed.\n\n"
5278          | RString _ ->
5279              pr "This function returns a string, or NULL on error.
5280 I<The caller must free the returned string after use>.\n\n"
5281          | RStringList _ ->
5282              pr "This function returns a NULL-terminated array of strings
5283 (like L<environ(3)>), or NULL if there was an error.
5284 I<The caller must free the strings and the array after use>.\n\n"
5285          | RStruct (_, typ) ->
5286              pr "This function returns a C<struct guestfs_%s *>,
5287 or NULL if there was an error.
5288 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
5289          | RStructList (_, typ) ->
5290              pr "This function returns a C<struct guestfs_%s_list *>
5291 (see E<lt>guestfs-structs.hE<gt>),
5292 or NULL if there was an error.
5293 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
5294          | RHashtable _ ->
5295              pr "This function returns a NULL-terminated array of
5296 strings, or NULL if there was an error.
5297 The array of strings will always have length C<2n+1>, where
5298 C<n> keys and values alternate, followed by the trailing NULL entry.
5299 I<The caller must free the strings and the array after use>.\n\n"
5300          | RBufferOut _ ->
5301              pr "This function returns a buffer, or NULL on error.
5302 The size of the returned buffer is written to C<*size_r>.
5303 I<The caller must free the returned buffer after use>.\n\n"
5304         );
5305         if List.mem ProtocolLimitWarning flags then
5306           pr "%s\n\n" protocol_limit_warning;
5307         if List.mem DangerWillRobinson flags then
5308           pr "%s\n\n" danger_will_robinson;
5309         match deprecation_notice flags with
5310         | None -> ()
5311         | Some txt -> pr "%s\n\n" txt
5312       )
5313   ) all_functions_sorted
5314
5315 and generate_structs_pod () =
5316   (* Structs documentation. *)
5317   List.iter (
5318     fun (typ, cols) ->
5319       pr "=head2 guestfs_%s\n" typ;
5320       pr "\n";
5321       pr " struct guestfs_%s {\n" typ;
5322       List.iter (
5323         function
5324         | name, FChar -> pr "   char %s;\n" name
5325         | name, FUInt32 -> pr "   uint32_t %s;\n" name
5326         | name, FInt32 -> pr "   int32_t %s;\n" name
5327         | name, (FUInt64|FBytes) -> pr "   uint64_t %s;\n" name
5328         | name, FInt64 -> pr "   int64_t %s;\n" name
5329         | name, FString -> pr "   char *%s;\n" name
5330         | name, FBuffer ->
5331             pr "   /* The next two fields describe a byte array. */\n";
5332             pr "   uint32_t %s_len;\n" name;
5333             pr "   char *%s;\n" name
5334         | name, FUUID ->
5335             pr "   /* The next field is NOT nul-terminated, be careful when printing it: */\n";
5336             pr "   char %s[32];\n" name
5337         | name, FOptPercent ->
5338             pr "   /* The next field is [0..100] or -1 meaning 'not present': */\n";
5339             pr "   float %s;\n" name
5340       ) cols;
5341       pr " };\n";
5342       pr " \n";
5343       pr " struct guestfs_%s_list {\n" typ;
5344       pr "   uint32_t len; /* Number of elements in list. */\n";
5345       pr "   struct guestfs_%s *val; /* Elements. */\n" typ;
5346       pr " };\n";
5347       pr " \n";
5348       pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
5349       pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
5350         typ typ;
5351       pr "\n"
5352   ) structs
5353
5354 and generate_availability_pod () =
5355   (* Availability documentation. *)
5356   pr "=over 4\n";
5357   pr "\n";
5358   List.iter (
5359     fun (group, functions) ->
5360       pr "=item B<%s>\n" group;
5361       pr "\n";
5362       pr "The following functions:\n";
5363       List.iter (pr "L</guestfs_%s>\n") functions;
5364       pr "\n"
5365   ) optgroups;
5366   pr "=back\n";
5367   pr "\n"
5368
5369 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
5370  * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
5371  *
5372  * We have to use an underscore instead of a dash because otherwise
5373  * rpcgen generates incorrect code.
5374  *
5375  * This header is NOT exported to clients, but see also generate_structs_h.
5376  *)
5377 and generate_xdr () =
5378   generate_header CStyle LGPLv2plus;
5379
5380   (* This has to be defined to get around a limitation in Sun's rpcgen. *)
5381   pr "typedef string str<>;\n";
5382   pr "\n";
5383
5384   (* Internal structures. *)
5385   List.iter (
5386     function
5387     | typ, cols ->
5388         pr "struct guestfs_int_%s {\n" typ;
5389         List.iter (function
5390                    | name, FChar -> pr "  char %s;\n" name
5391                    | name, FString -> pr "  string %s<>;\n" name
5392                    | name, FBuffer -> pr "  opaque %s<>;\n" name
5393                    | name, FUUID -> pr "  opaque %s[32];\n" name
5394                    | name, (FInt32|FUInt32) -> pr "  int %s;\n" name
5395                    | name, (FInt64|FUInt64|FBytes) -> pr "  hyper %s;\n" name
5396                    | name, FOptPercent -> pr "  float %s;\n" name
5397                   ) cols;
5398         pr "};\n";
5399         pr "\n";
5400         pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
5401         pr "\n";
5402   ) structs;
5403
5404   List.iter (
5405     fun (shortname, style, _, _, _, _, _) ->
5406       let name = "guestfs_" ^ shortname in
5407
5408       (match snd style with
5409        | [] -> ()
5410        | args ->
5411            pr "struct %s_args {\n" name;
5412            List.iter (
5413              function
5414              | Pathname n | Device n | Dev_or_Path n | String n ->
5415                  pr "  string %s<>;\n" n
5416              | OptString n -> pr "  str *%s;\n" n
5417              | StringList n | DeviceList n -> pr "  str %s<>;\n" n
5418              | Bool n -> pr "  bool %s;\n" n
5419              | Int n -> pr "  int %s;\n" n
5420              | Int64 n -> pr "  hyper %s;\n" n
5421              | FileIn _ | FileOut _ -> ()
5422            ) args;
5423            pr "};\n\n"
5424       );
5425       (match fst style with
5426        | RErr -> ()
5427        | RInt n ->
5428            pr "struct %s_ret {\n" name;
5429            pr "  int %s;\n" n;
5430            pr "};\n\n"
5431        | RInt64 n ->
5432            pr "struct %s_ret {\n" name;
5433            pr "  hyper %s;\n" n;
5434            pr "};\n\n"
5435        | RBool n ->
5436            pr "struct %s_ret {\n" name;
5437            pr "  bool %s;\n" n;
5438            pr "};\n\n"
5439        | RConstString _ | RConstOptString _ ->
5440            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5441        | RString n ->
5442            pr "struct %s_ret {\n" name;
5443            pr "  string %s<>;\n" n;
5444            pr "};\n\n"
5445        | RStringList n ->
5446            pr "struct %s_ret {\n" name;
5447            pr "  str %s<>;\n" n;
5448            pr "};\n\n"
5449        | RStruct (n, typ) ->
5450            pr "struct %s_ret {\n" name;
5451            pr "  guestfs_int_%s %s;\n" typ n;
5452            pr "};\n\n"
5453        | RStructList (n, typ) ->
5454            pr "struct %s_ret {\n" name;
5455            pr "  guestfs_int_%s_list %s;\n" typ n;
5456            pr "};\n\n"
5457        | RHashtable n ->
5458            pr "struct %s_ret {\n" name;
5459            pr "  str %s<>;\n" n;
5460            pr "};\n\n"
5461        | RBufferOut n ->
5462            pr "struct %s_ret {\n" name;
5463            pr "  opaque %s<>;\n" n;
5464            pr "};\n\n"
5465       );
5466   ) daemon_functions;
5467
5468   (* Table of procedure numbers. *)
5469   pr "enum guestfs_procedure {\n";
5470   List.iter (
5471     fun (shortname, _, proc_nr, _, _, _, _) ->
5472       pr "  GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
5473   ) daemon_functions;
5474   pr "  GUESTFS_PROC_NR_PROCS\n";
5475   pr "};\n";
5476   pr "\n";
5477
5478   (* Having to choose a maximum message size is annoying for several
5479    * reasons (it limits what we can do in the API), but it (a) makes
5480    * the protocol a lot simpler, and (b) provides a bound on the size
5481    * of the daemon which operates in limited memory space.
5482    *)
5483   pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
5484   pr "\n";
5485
5486   (* Message header, etc. *)
5487   pr "\
5488 /* The communication protocol is now documented in the guestfs(3)
5489  * manpage.
5490  */
5491
5492 const GUESTFS_PROGRAM = 0x2000F5F5;
5493 const GUESTFS_PROTOCOL_VERSION = 1;
5494
5495 /* These constants must be larger than any possible message length. */
5496 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
5497 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
5498
5499 enum guestfs_message_direction {
5500   GUESTFS_DIRECTION_CALL = 0,        /* client -> daemon */
5501   GUESTFS_DIRECTION_REPLY = 1        /* daemon -> client */
5502 };
5503
5504 enum guestfs_message_status {
5505   GUESTFS_STATUS_OK = 0,
5506   GUESTFS_STATUS_ERROR = 1
5507 };
5508
5509 const GUESTFS_ERROR_LEN = 256;
5510
5511 struct guestfs_message_error {
5512   string error_message<GUESTFS_ERROR_LEN>;
5513 };
5514
5515 struct guestfs_message_header {
5516   unsigned prog;                     /* GUESTFS_PROGRAM */
5517   unsigned vers;                     /* GUESTFS_PROTOCOL_VERSION */
5518   guestfs_procedure proc;            /* GUESTFS_PROC_x */
5519   guestfs_message_direction direction;
5520   unsigned serial;                   /* message serial number */
5521   guestfs_message_status status;
5522 };
5523
5524 const GUESTFS_MAX_CHUNK_SIZE = 8192;
5525
5526 struct guestfs_chunk {
5527   int cancel;                        /* if non-zero, transfer is cancelled */
5528   /* data size is 0 bytes if the transfer has finished successfully */
5529   opaque data<GUESTFS_MAX_CHUNK_SIZE>;
5530 };
5531 "
5532
5533 (* Generate the guestfs-structs.h file. *)
5534 and generate_structs_h () =
5535   generate_header CStyle LGPLv2plus;
5536
5537   (* This is a public exported header file containing various
5538    * structures.  The structures are carefully written to have
5539    * exactly the same in-memory format as the XDR structures that
5540    * we use on the wire to the daemon.  The reason for creating
5541    * copies of these structures here is just so we don't have to
5542    * export the whole of guestfs_protocol.h (which includes much
5543    * unrelated and XDR-dependent stuff that we don't want to be
5544    * public, or required by clients).
5545    *
5546    * To reiterate, we will pass these structures to and from the
5547    * client with a simple assignment or memcpy, so the format
5548    * must be identical to what rpcgen / the RFC defines.
5549    *)
5550
5551   (* Public structures. *)
5552   List.iter (
5553     fun (typ, cols) ->
5554       pr "struct guestfs_%s {\n" typ;
5555       List.iter (
5556         function
5557         | name, FChar -> pr "  char %s;\n" name
5558         | name, FString -> pr "  char *%s;\n" name
5559         | name, FBuffer ->
5560             pr "  uint32_t %s_len;\n" name;
5561             pr "  char *%s;\n" name
5562         | name, FUUID -> pr "  char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
5563         | name, FUInt32 -> pr "  uint32_t %s;\n" name
5564         | name, FInt32 -> pr "  int32_t %s;\n" name
5565         | name, (FUInt64|FBytes) -> pr "  uint64_t %s;\n" name
5566         | name, FInt64 -> pr "  int64_t %s;\n" name
5567         | name, FOptPercent -> pr "  float %s; /* [0..100] or -1 */\n" name
5568       ) cols;
5569       pr "};\n";
5570       pr "\n";
5571       pr "struct guestfs_%s_list {\n" typ;
5572       pr "  uint32_t len;\n";
5573       pr "  struct guestfs_%s *val;\n" typ;
5574       pr "};\n";
5575       pr "\n";
5576       pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
5577       pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
5578       pr "\n"
5579   ) structs
5580
5581 (* Generate the guestfs-actions.h file. *)
5582 and generate_actions_h () =
5583   generate_header CStyle LGPLv2plus;
5584   List.iter (
5585     fun (shortname, style, _, _, _, _, _) ->
5586       let name = "guestfs_" ^ shortname in
5587       generate_prototype ~single_line:true ~newline:true ~handle:"g"
5588         name style
5589   ) all_functions
5590
5591 (* Generate the guestfs-internal-actions.h file. *)
5592 and generate_internal_actions_h () =
5593   generate_header CStyle LGPLv2plus;
5594   List.iter (
5595     fun (shortname, style, _, _, _, _, _) ->
5596       let name = "guestfs__" ^ shortname in
5597       generate_prototype ~single_line:true ~newline:true ~handle:"g"
5598         name style
5599   ) non_daemon_functions
5600
5601 (* Generate the client-side dispatch stubs. *)
5602 and generate_client_actions () =
5603   generate_header CStyle LGPLv2plus;
5604
5605   pr "\
5606 #include <stdio.h>
5607 #include <stdlib.h>
5608 #include <stdint.h>
5609 #include <string.h>
5610 #include <inttypes.h>
5611
5612 #include \"guestfs.h\"
5613 #include \"guestfs-internal.h\"
5614 #include \"guestfs-internal-actions.h\"
5615 #include \"guestfs_protocol.h\"
5616
5617 #define error guestfs_error
5618 //#define perrorf guestfs_perrorf
5619 #define safe_malloc guestfs_safe_malloc
5620 #define safe_realloc guestfs_safe_realloc
5621 //#define safe_strdup guestfs_safe_strdup
5622 #define safe_memdup guestfs_safe_memdup
5623
5624 /* Check the return message from a call for validity. */
5625 static int
5626 check_reply_header (guestfs_h *g,
5627                     const struct guestfs_message_header *hdr,
5628                     unsigned int proc_nr, unsigned int serial)
5629 {
5630   if (hdr->prog != GUESTFS_PROGRAM) {
5631     error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
5632     return -1;
5633   }
5634   if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
5635     error (g, \"wrong protocol version (%%d/%%d)\",
5636            hdr->vers, GUESTFS_PROTOCOL_VERSION);
5637     return -1;
5638   }
5639   if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
5640     error (g, \"unexpected message direction (%%d/%%d)\",
5641            hdr->direction, GUESTFS_DIRECTION_REPLY);
5642     return -1;
5643   }
5644   if (hdr->proc != proc_nr) {
5645     error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
5646     return -1;
5647   }
5648   if (hdr->serial != serial) {
5649     error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
5650     return -1;
5651   }
5652
5653   return 0;
5654 }
5655
5656 /* Check we are in the right state to run a high-level action. */
5657 static int
5658 check_state (guestfs_h *g, const char *caller)
5659 {
5660   if (!guestfs__is_ready (g)) {
5661     if (guestfs__is_config (g) || guestfs__is_launching (g))
5662       error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
5663         caller);
5664     else
5665       error (g, \"%%s called from the wrong state, %%d != READY\",
5666         caller, guestfs__get_state (g));
5667     return -1;
5668   }
5669   return 0;
5670 }
5671
5672 ";
5673
5674   (* Generate code to generate guestfish call traces. *)
5675   let trace_call shortname style =
5676     pr "  if (guestfs__get_trace (g)) {\n";
5677
5678     let needs_i =
5679       List.exists (function
5680                    | StringList _ | DeviceList _ -> true
5681                    | _ -> false) (snd style) in
5682     if needs_i then (
5683       pr "    int i;\n";
5684       pr "\n"
5685     );
5686
5687     pr "    printf (\"%s\");\n" shortname;
5688     List.iter (
5689       function
5690       | String n                        (* strings *)
5691       | Device n
5692       | Pathname n
5693       | Dev_or_Path n
5694       | FileIn n
5695       | FileOut n ->
5696           (* guestfish doesn't support string escaping, so neither do we *)
5697           pr "    printf (\" \\\"%%s\\\"\", %s);\n" n
5698       | OptString n ->                  (* string option *)
5699           pr "    if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
5700           pr "    else printf (\" null\");\n"
5701       | StringList n
5702       | DeviceList n ->                 (* string list *)
5703           pr "    putchar (' ');\n";
5704           pr "    putchar ('\"');\n";
5705           pr "    for (i = 0; %s[i]; ++i) {\n" n;
5706           pr "      if (i > 0) putchar (' ');\n";
5707           pr "      fputs (%s[i], stdout);\n" n;
5708           pr "    }\n";
5709           pr "    putchar ('\"');\n";
5710       | Bool n ->                       (* boolean *)
5711           pr "    fputs (%s ? \" true\" : \" false\", stdout);\n" n
5712       | Int n ->                        (* int *)
5713           pr "    printf (\" %%d\", %s);\n" n
5714       | Int64 n ->
5715           pr "    printf (\" %%\" PRIi64, %s);\n" n
5716     ) (snd style);
5717     pr "    putchar ('\\n');\n";
5718     pr "  }\n";
5719     pr "\n";
5720   in
5721
5722   (* For non-daemon functions, generate a wrapper around each function. *)
5723   List.iter (
5724     fun (shortname, style, _, _, _, _, _) ->
5725       let name = "guestfs_" ^ shortname in
5726
5727       generate_prototype ~extern:false ~semicolon:false ~newline:true
5728         ~handle:"g" name style;
5729       pr "{\n";
5730       trace_call shortname style;
5731       pr "  return guestfs__%s " shortname;
5732       generate_c_call_args ~handle:"g" style;
5733       pr ";\n";
5734       pr "}\n";
5735       pr "\n"
5736   ) non_daemon_functions;
5737
5738   (* Client-side stubs for each function. *)
5739   List.iter (
5740     fun (shortname, style, _, _, _, _, _) ->
5741       let name = "guestfs_" ^ shortname in
5742
5743       (* Generate the action stub. *)
5744       generate_prototype ~extern:false ~semicolon:false ~newline:true
5745         ~handle:"g" name style;
5746
5747       let error_code =
5748         match fst style with
5749         | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
5750         | RConstString _ | RConstOptString _ ->
5751             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5752         | RString _ | RStringList _
5753         | RStruct _ | RStructList _
5754         | RHashtable _ | RBufferOut _ ->
5755             "NULL" in
5756
5757       pr "{\n";
5758
5759       (match snd style with
5760        | [] -> ()
5761        | _ -> pr "  struct %s_args args;\n" name
5762       );
5763
5764       pr "  guestfs_message_header hdr;\n";
5765       pr "  guestfs_message_error err;\n";
5766       let has_ret =
5767         match fst style with
5768         | RErr -> false
5769         | RConstString _ | RConstOptString _ ->
5770             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5771         | RInt _ | RInt64 _
5772         | RBool _ | RString _ | RStringList _
5773         | RStruct _ | RStructList _
5774         | RHashtable _ | RBufferOut _ ->
5775             pr "  struct %s_ret ret;\n" name;
5776             true in
5777
5778       pr "  int serial;\n";
5779       pr "  int r;\n";
5780       pr "\n";
5781       trace_call shortname style;
5782       pr "  if (check_state (g, \"%s\") == -1) return %s;\n"
5783         shortname error_code;
5784       pr "  guestfs___set_busy (g);\n";
5785       pr "\n";
5786
5787       (* Send the main header and arguments. *)
5788       (match snd style with
5789        | [] ->
5790            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
5791              (String.uppercase shortname)
5792        | args ->
5793            List.iter (
5794              function
5795              | Pathname n | Device n | Dev_or_Path n | String n ->
5796                  pr "  args.%s = (char *) %s;\n" n n
5797              | OptString n ->
5798                  pr "  args.%s = %s ? (char **) &%s : NULL;\n" n n n
5799              | StringList n | DeviceList n ->
5800                  pr "  args.%s.%s_val = (char **) %s;\n" n n n;
5801                  pr "  for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
5802              | Bool n ->
5803                  pr "  args.%s = %s;\n" n n
5804              | Int n ->
5805                  pr "  args.%s = %s;\n" n n
5806              | Int64 n ->
5807                  pr "  args.%s = %s;\n" n n
5808              | FileIn _ | FileOut _ -> ()
5809            ) args;
5810            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
5811              (String.uppercase shortname);
5812            pr "        (xdrproc_t) xdr_%s_args, (char *) &args);\n"
5813              name;
5814       );
5815       pr "  if (serial == -1) {\n";
5816       pr "    guestfs___end_busy (g);\n";
5817       pr "    return %s;\n" error_code;
5818       pr "  }\n";
5819       pr "\n";
5820
5821       (* Send any additional files (FileIn) requested. *)
5822       let need_read_reply_label = ref false in
5823       List.iter (
5824         function
5825         | FileIn n ->
5826             pr "  r = guestfs___send_file (g, %s);\n" n;
5827             pr "  if (r == -1) {\n";
5828             pr "    guestfs___end_busy (g);\n";
5829             pr "    return %s;\n" error_code;
5830             pr "  }\n";
5831             pr "  if (r == -2) /* daemon cancelled */\n";
5832             pr "    goto read_reply;\n";
5833             need_read_reply_label := true;
5834             pr "\n";
5835         | _ -> ()
5836       ) (snd style);
5837
5838       (* Wait for the reply from the remote end. *)
5839       if !need_read_reply_label then pr " read_reply:\n";
5840       pr "  memset (&hdr, 0, sizeof hdr);\n";
5841       pr "  memset (&err, 0, sizeof err);\n";
5842       if has_ret then pr "  memset (&ret, 0, sizeof ret);\n";
5843       pr "\n";
5844       pr "  r = guestfs___recv (g, \"%s\", &hdr, &err,\n        " shortname;
5845       if not has_ret then
5846         pr "NULL, NULL"
5847       else
5848         pr "(xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret" shortname;
5849       pr ");\n";
5850
5851       pr "  if (r == -1) {\n";
5852       pr "    guestfs___end_busy (g);\n";
5853       pr "    return %s;\n" error_code;
5854       pr "  }\n";
5855       pr "\n";
5856
5857       pr "  if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
5858         (String.uppercase shortname);
5859       pr "    guestfs___end_busy (g);\n";
5860       pr "    return %s;\n" error_code;
5861       pr "  }\n";
5862       pr "\n";
5863
5864       pr "  if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
5865       pr "    error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
5866       pr "    free (err.error_message);\n";
5867       pr "    guestfs___end_busy (g);\n";
5868       pr "    return %s;\n" error_code;
5869       pr "  }\n";
5870       pr "\n";
5871
5872       (* Expecting to receive further files (FileOut)? *)
5873       List.iter (
5874         function
5875         | FileOut n ->
5876             pr "  if (guestfs___recv_file (g, %s) == -1) {\n" n;
5877             pr "    guestfs___end_busy (g);\n";
5878             pr "    return %s;\n" error_code;
5879             pr "  }\n";
5880             pr "\n";
5881         | _ -> ()
5882       ) (snd style);
5883
5884       pr "  guestfs___end_busy (g);\n";
5885
5886       (match fst style with
5887        | RErr -> pr "  return 0;\n"
5888        | RInt n | RInt64 n | RBool n ->
5889            pr "  return ret.%s;\n" n
5890        | RConstString _ | RConstOptString _ ->
5891            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5892        | RString n ->
5893            pr "  return ret.%s; /* caller will free */\n" n
5894        | RStringList n | RHashtable n ->
5895            pr "  /* caller will free this, but we need to add a NULL entry */\n";
5896            pr "  ret.%s.%s_val =\n" n n;
5897            pr "    safe_realloc (g, ret.%s.%s_val,\n" n n;
5898            pr "                  sizeof (char *) * (ret.%s.%s_len + 1));\n"
5899              n n;
5900            pr "  ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
5901            pr "  return ret.%s.%s_val;\n" n n
5902        | RStruct (n, _) ->
5903            pr "  /* caller will free this */\n";
5904            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5905        | RStructList (n, _) ->
5906            pr "  /* caller will free this */\n";
5907            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5908        | RBufferOut n ->
5909            pr "  /* RBufferOut is tricky: If the buffer is zero-length, then\n";
5910            pr "   * _val might be NULL here.  To make the API saner for\n";
5911            pr "   * callers, we turn this case into a unique pointer (using\n";
5912            pr "   * malloc(1)).\n";
5913            pr "   */\n";
5914            pr "  if (ret.%s.%s_len > 0) {\n" n n;
5915            pr "    *size_r = ret.%s.%s_len;\n" n n;
5916            pr "    return ret.%s.%s_val; /* caller will free */\n" n n;
5917            pr "  } else {\n";
5918            pr "    free (ret.%s.%s_val);\n" n n;
5919            pr "    char *p = safe_malloc (g, 1);\n";
5920            pr "    *size_r = ret.%s.%s_len;\n" n n;
5921            pr "    return p;\n";
5922            pr "  }\n";
5923       );
5924
5925       pr "}\n\n"
5926   ) daemon_functions;
5927
5928   (* Functions to free structures. *)
5929   pr "/* Structure-freeing functions.  These rely on the fact that the\n";
5930   pr " * structure format is identical to the XDR format.  See note in\n";
5931   pr " * generator.ml.\n";
5932   pr " */\n";
5933   pr "\n";
5934
5935   List.iter (
5936     fun (typ, _) ->
5937       pr "void\n";
5938       pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
5939       pr "{\n";
5940       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
5941       pr "  free (x);\n";
5942       pr "}\n";
5943       pr "\n";
5944
5945       pr "void\n";
5946       pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
5947       pr "{\n";
5948       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
5949       pr "  free (x);\n";
5950       pr "}\n";
5951       pr "\n";
5952
5953   ) structs;
5954
5955 (* Generate daemon/actions.h. *)
5956 and generate_daemon_actions_h () =
5957   generate_header CStyle GPLv2plus;
5958
5959   pr "#include \"../src/guestfs_protocol.h\"\n";
5960   pr "\n";
5961
5962   List.iter (
5963     fun (name, style, _, _, _, _, _) ->
5964       generate_prototype
5965         ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
5966         name style;
5967   ) daemon_functions
5968
5969 (* Generate the linker script which controls the visibility of
5970  * symbols in the public ABI and ensures no other symbols get
5971  * exported accidentally.
5972  *)
5973 and generate_linker_script () =
5974   generate_header HashStyle GPLv2plus;
5975
5976   let globals = [
5977     "guestfs_create";
5978     "guestfs_close";
5979     "guestfs_get_error_handler";
5980     "guestfs_get_out_of_memory_handler";
5981     "guestfs_last_error";
5982     "guestfs_set_error_handler";
5983     "guestfs_set_launch_done_callback";
5984     "guestfs_set_log_message_callback";
5985     "guestfs_set_out_of_memory_handler";
5986     "guestfs_set_subprocess_quit_callback";
5987
5988     (* Unofficial parts of the API: the bindings code use these
5989      * functions, so it is useful to export them.
5990      *)
5991     "guestfs_safe_calloc";
5992     "guestfs_safe_malloc";
5993   ] in
5994   let functions =
5995     List.map (fun (name, _, _, _, _, _, _) -> "guestfs_" ^ name)
5996       all_functions in
5997   let structs =
5998     List.concat (
5999       List.map (fun (typ, _) ->
6000                   ["guestfs_free_" ^ typ; "guestfs_free_" ^ typ ^ "_list"])
6001         structs
6002     ) in
6003   let globals = List.sort compare (globals @ functions @ structs) in
6004
6005   pr "{\n";
6006   pr "    global:\n";
6007   List.iter (pr "        %s;\n") globals;
6008   pr "\n";
6009
6010   pr "    local:\n";
6011   pr "        *;\n";
6012   pr "};\n"
6013
6014 (* Generate the server-side stubs. *)
6015 and generate_daemon_actions () =
6016   generate_header CStyle GPLv2plus;
6017
6018   pr "#include <config.h>\n";
6019   pr "\n";
6020   pr "#include <stdio.h>\n";
6021   pr "#include <stdlib.h>\n";
6022   pr "#include <string.h>\n";
6023   pr "#include <inttypes.h>\n";
6024   pr "#include <rpc/types.h>\n";
6025   pr "#include <rpc/xdr.h>\n";
6026   pr "\n";
6027   pr "#include \"daemon.h\"\n";
6028   pr "#include \"c-ctype.h\"\n";
6029   pr "#include \"../src/guestfs_protocol.h\"\n";
6030   pr "#include \"actions.h\"\n";
6031   pr "\n";
6032
6033   List.iter (
6034     fun (name, style, _, _, _, _, _) ->
6035       (* Generate server-side stubs. *)
6036       pr "static void %s_stub (XDR *xdr_in)\n" name;
6037       pr "{\n";
6038       let error_code =
6039         match fst style with
6040         | RErr | RInt _ -> pr "  int r;\n"; "-1"
6041         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
6042         | RBool _ -> pr "  int r;\n"; "-1"
6043         | RConstString _ | RConstOptString _ ->
6044             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6045         | RString _ -> pr "  char *r;\n"; "NULL"
6046         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
6047         | RStruct (_, typ) -> pr "  guestfs_int_%s *r;\n" typ; "NULL"
6048         | RStructList (_, typ) -> pr "  guestfs_int_%s_list *r;\n" typ; "NULL"
6049         | RBufferOut _ ->
6050             pr "  size_t size = 1;\n";
6051             pr "  char *r;\n";
6052             "NULL" in
6053
6054       (match snd style with
6055        | [] -> ()
6056        | args ->
6057            pr "  struct guestfs_%s_args args;\n" name;
6058            List.iter (
6059              function
6060              | Device n | Dev_or_Path n
6061              | Pathname n
6062              | String n -> ()
6063              | OptString n -> pr "  char *%s;\n" n
6064              | StringList n | DeviceList n -> pr "  char **%s;\n" n
6065              | Bool n -> pr "  int %s;\n" n
6066              | Int n -> pr "  int %s;\n" n
6067              | Int64 n -> pr "  int64_t %s;\n" n
6068              | FileIn _ | FileOut _ -> ()
6069            ) args
6070       );
6071       pr "\n";
6072
6073       let is_filein =
6074         List.exists (function FileIn _ -> true | _ -> false) (snd style) in
6075
6076       (match snd style with
6077        | [] -> ()
6078        | args ->
6079            pr "  memset (&args, 0, sizeof args);\n";
6080            pr "\n";
6081            pr "  if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
6082            if is_filein then
6083              pr "    cancel_receive ();\n";
6084            pr "    reply_with_error (\"daemon failed to decode procedure arguments\");\n";
6085            pr "    goto done;\n";
6086            pr "  }\n";
6087            let pr_args n =
6088              pr "  char *%s = args.%s;\n" n n
6089            in
6090            let pr_list_handling_code n =
6091              pr "  %s = realloc (args.%s.%s_val,\n" n n n;
6092              pr "                sizeof (char *) * (args.%s.%s_len+1));\n" n n;
6093              pr "  if (%s == NULL) {\n" n;
6094              if is_filein then
6095                pr "    cancel_receive ();\n";
6096              pr "    reply_with_perror (\"realloc\");\n";
6097              pr "    goto done;\n";
6098              pr "  }\n";
6099              pr "  %s[args.%s.%s_len] = NULL;\n" n n n;
6100              pr "  args.%s.%s_val = %s;\n" n n n;
6101            in
6102            List.iter (
6103              function
6104              | Pathname n ->
6105                  pr_args n;
6106                  pr "  ABS_PATH (%s, %s, goto done);\n"
6107                    n (if is_filein then "cancel_receive ()" else "");
6108              | Device n ->
6109                  pr_args n;
6110                  pr "  RESOLVE_DEVICE (%s, %s, goto done);\n"
6111                    n (if is_filein then "cancel_receive ()" else "");
6112              | Dev_or_Path n ->
6113                  pr_args n;
6114                  pr "  REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, %s, goto done);\n"
6115                    n (if is_filein then "cancel_receive ()" else "");
6116              | String n -> pr_args n
6117              | OptString n -> pr "  %s = args.%s ? *args.%s : NULL;\n" n n n
6118              | StringList n ->
6119                  pr_list_handling_code n;
6120              | DeviceList n ->
6121                  pr_list_handling_code n;
6122                  pr "  /* Ensure that each is a device,\n";
6123                  pr "   * and perform device name translation. */\n";
6124                  pr "  { int pvi; for (pvi = 0; physvols[pvi] != NULL; ++pvi)\n";
6125                  pr "    RESOLVE_DEVICE (physvols[pvi], %s, goto done);\n"
6126                    (if is_filein then "cancel_receive ()" else "");
6127                  pr "  }\n";
6128              | Bool n -> pr "  %s = args.%s;\n" n n
6129              | Int n -> pr "  %s = args.%s;\n" n n
6130              | Int64 n -> pr "  %s = args.%s;\n" n n
6131              | FileIn _ | FileOut _ -> ()
6132            ) args;
6133            pr "\n"
6134       );
6135
6136
6137       (* this is used at least for do_equal *)
6138       if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
6139         (* Emit NEED_ROOT just once, even when there are two or
6140            more Pathname args *)
6141         pr "  NEED_ROOT (%s, goto done);\n"
6142           (if is_filein then "cancel_receive ()" else "");
6143       );
6144
6145       (* Don't want to call the impl with any FileIn or FileOut
6146        * parameters, since these go "outside" the RPC protocol.
6147        *)
6148       let args' =
6149         List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
6150           (snd style) in
6151       pr "  r = do_%s " name;
6152       generate_c_call_args (fst style, args');
6153       pr ";\n";
6154
6155       (match fst style with
6156        | RErr | RInt _ | RInt64 _ | RBool _
6157        | RConstString _ | RConstOptString _
6158        | RString _ | RStringList _ | RHashtable _
6159        | RStruct (_, _) | RStructList (_, _) ->
6160            pr "  if (r == %s)\n" error_code;
6161            pr "    /* do_%s has already called reply_with_error */\n" name;
6162            pr "    goto done;\n";
6163            pr "\n"
6164        | RBufferOut _ ->
6165            pr "  /* size == 0 && r == NULL could be a non-error case (just\n";
6166            pr "   * an ordinary zero-length buffer), so be careful ...\n";
6167            pr "   */\n";
6168            pr "  if (size == 1 && r == %s)\n" error_code;
6169            pr "    /* do_%s has already called reply_with_error */\n" name;
6170            pr "    goto done;\n";
6171            pr "\n"
6172       );
6173
6174       (* If there are any FileOut parameters, then the impl must
6175        * send its own reply.
6176        *)
6177       let no_reply =
6178         List.exists (function FileOut _ -> true | _ -> false) (snd style) in
6179       if no_reply then
6180         pr "  /* do_%s has already sent a reply */\n" name
6181       else (
6182         match fst style with
6183         | RErr -> pr "  reply (NULL, NULL);\n"
6184         | RInt n | RInt64 n | RBool n ->
6185             pr "  struct guestfs_%s_ret ret;\n" name;
6186             pr "  ret.%s = r;\n" n;
6187             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6188               name
6189         | RConstString _ | RConstOptString _ ->
6190             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6191         | RString n ->
6192             pr "  struct guestfs_%s_ret ret;\n" name;
6193             pr "  ret.%s = r;\n" n;
6194             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6195               name;
6196             pr "  free (r);\n"
6197         | RStringList n | RHashtable n ->
6198             pr "  struct guestfs_%s_ret ret;\n" name;
6199             pr "  ret.%s.%s_len = count_strings (r);\n" n n;
6200             pr "  ret.%s.%s_val = r;\n" n n;
6201             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6202               name;
6203             pr "  free_strings (r);\n"
6204         | RStruct (n, _) ->
6205             pr "  struct guestfs_%s_ret ret;\n" name;
6206             pr "  ret.%s = *r;\n" n;
6207             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6208               name;
6209             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6210               name
6211         | RStructList (n, _) ->
6212             pr "  struct guestfs_%s_ret ret;\n" name;
6213             pr "  ret.%s = *r;\n" n;
6214             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6215               name;
6216             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6217               name
6218         | RBufferOut n ->
6219             pr "  struct guestfs_%s_ret ret;\n" name;
6220             pr "  ret.%s.%s_val = r;\n" n n;
6221             pr "  ret.%s.%s_len = size;\n" n n;
6222             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6223               name;
6224             pr "  free (r);\n"
6225       );
6226
6227       (* Free the args. *)
6228       pr "done:\n";
6229       (match snd style with
6230        | [] -> ()
6231        | _ ->
6232            pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
6233              name
6234       );
6235       pr "  return;\n";
6236       pr "}\n\n";
6237   ) daemon_functions;
6238
6239   (* Dispatch function. *)
6240   pr "void dispatch_incoming_message (XDR *xdr_in)\n";
6241   pr "{\n";
6242   pr "  switch (proc_nr) {\n";
6243
6244   List.iter (
6245     fun (name, style, _, _, _, _, _) ->
6246       pr "    case GUESTFS_PROC_%s:\n" (String.uppercase name);
6247       pr "      %s_stub (xdr_in);\n" name;
6248       pr "      break;\n"
6249   ) daemon_functions;
6250
6251   pr "    default:\n";
6252   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";
6253   pr "  }\n";
6254   pr "}\n";
6255   pr "\n";
6256
6257   (* LVM columns and tokenization functions. *)
6258   (* XXX This generates crap code.  We should rethink how we
6259    * do this parsing.
6260    *)
6261   List.iter (
6262     function
6263     | typ, cols ->
6264         pr "static const char *lvm_%s_cols = \"%s\";\n"
6265           typ (String.concat "," (List.map fst cols));
6266         pr "\n";
6267
6268         pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
6269         pr "{\n";
6270         pr "  char *tok, *p, *next;\n";
6271         pr "  int i, j;\n";
6272         pr "\n";
6273         (*
6274           pr "  fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
6275           pr "\n";
6276         *)
6277         pr "  if (!str) {\n";
6278         pr "    fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
6279         pr "    return -1;\n";
6280         pr "  }\n";
6281         pr "  if (!*str || c_isspace (*str)) {\n";
6282         pr "    fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
6283         pr "    return -1;\n";
6284         pr "  }\n";
6285         pr "  tok = str;\n";
6286         List.iter (
6287           fun (name, coltype) ->
6288             pr "  if (!tok) {\n";
6289             pr "    fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
6290             pr "    return -1;\n";
6291             pr "  }\n";
6292             pr "  p = strchrnul (tok, ',');\n";
6293             pr "  if (*p) next = p+1; else next = NULL;\n";
6294             pr "  *p = '\\0';\n";
6295             (match coltype with
6296              | FString ->
6297                  pr "  r->%s = strdup (tok);\n" name;
6298                  pr "  if (r->%s == NULL) {\n" name;
6299                  pr "    perror (\"strdup\");\n";
6300                  pr "    return -1;\n";
6301                  pr "  }\n"
6302              | FUUID ->
6303                  pr "  for (i = j = 0; i < 32; ++j) {\n";
6304                  pr "    if (tok[j] == '\\0') {\n";
6305                  pr "      fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
6306                  pr "      return -1;\n";
6307                  pr "    } else if (tok[j] != '-')\n";
6308                  pr "      r->%s[i++] = tok[j];\n" name;
6309                  pr "  }\n";
6310              | FBytes ->
6311                  pr "  if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
6312                  pr "    fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6313                  pr "    return -1;\n";
6314                  pr "  }\n";
6315              | FInt64 ->
6316                  pr "  if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
6317                  pr "    fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6318                  pr "    return -1;\n";
6319                  pr "  }\n";
6320              | FOptPercent ->
6321                  pr "  if (tok[0] == '\\0')\n";
6322                  pr "    r->%s = -1;\n" name;
6323                  pr "  else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
6324                  pr "    fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6325                  pr "    return -1;\n";
6326                  pr "  }\n";
6327              | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
6328                  assert false (* can never be an LVM column *)
6329             );
6330             pr "  tok = next;\n";
6331         ) cols;
6332
6333         pr "  if (tok != NULL) {\n";
6334         pr "    fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
6335         pr "    return -1;\n";
6336         pr "  }\n";
6337         pr "  return 0;\n";
6338         pr "}\n";
6339         pr "\n";
6340
6341         pr "guestfs_int_lvm_%s_list *\n" typ;
6342         pr "parse_command_line_%ss (void)\n" typ;
6343         pr "{\n";
6344         pr "  char *out, *err;\n";
6345         pr "  char *p, *pend;\n";
6346         pr "  int r, i;\n";
6347         pr "  guestfs_int_lvm_%s_list *ret;\n" typ;
6348         pr "  void *newp;\n";
6349         pr "\n";
6350         pr "  ret = malloc (sizeof *ret);\n";
6351         pr "  if (!ret) {\n";
6352         pr "    reply_with_perror (\"malloc\");\n";
6353         pr "    return NULL;\n";
6354         pr "  }\n";
6355         pr "\n";
6356         pr "  ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
6357         pr "  ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
6358         pr "\n";
6359         pr "  r = command (&out, &err,\n";
6360         pr "           \"lvm\", \"%ss\",\n" typ;
6361         pr "           \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
6362         pr "           \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
6363         pr "  if (r == -1) {\n";
6364         pr "    reply_with_error (\"%%s\", err);\n";
6365         pr "    free (out);\n";
6366         pr "    free (err);\n";
6367         pr "    free (ret);\n";
6368         pr "    return NULL;\n";
6369         pr "  }\n";
6370         pr "\n";
6371         pr "  free (err);\n";
6372         pr "\n";
6373         pr "  /* Tokenize each line of the output. */\n";
6374         pr "  p = out;\n";
6375         pr "  i = 0;\n";
6376         pr "  while (p) {\n";
6377         pr "    pend = strchr (p, '\\n');       /* Get the next line of output. */\n";
6378         pr "    if (pend) {\n";
6379         pr "      *pend = '\\0';\n";
6380         pr "      pend++;\n";
6381         pr "    }\n";
6382         pr "\n";
6383         pr "    while (*p && c_isspace (*p))    /* Skip any leading whitespace. */\n";
6384         pr "      p++;\n";
6385         pr "\n";
6386         pr "    if (!*p) {                      /* Empty line?  Skip it. */\n";
6387         pr "      p = pend;\n";
6388         pr "      continue;\n";
6389         pr "    }\n";
6390         pr "\n";
6391         pr "    /* Allocate some space to store this next entry. */\n";
6392         pr "    newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
6393         pr "                sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
6394         pr "    if (newp == NULL) {\n";
6395         pr "      reply_with_perror (\"realloc\");\n";
6396         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6397         pr "      free (ret);\n";
6398         pr "      free (out);\n";
6399         pr "      return NULL;\n";
6400         pr "    }\n";
6401         pr "    ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
6402         pr "\n";
6403         pr "    /* Tokenize the next entry. */\n";
6404         pr "    r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
6405         pr "    if (r == -1) {\n";
6406         pr "      reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
6407         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6408         pr "      free (ret);\n";
6409         pr "      free (out);\n";
6410         pr "      return NULL;\n";
6411         pr "    }\n";
6412         pr "\n";
6413         pr "    ++i;\n";
6414         pr "    p = pend;\n";
6415         pr "  }\n";
6416         pr "\n";
6417         pr "  ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
6418         pr "\n";
6419         pr "  free (out);\n";
6420         pr "  return ret;\n";
6421         pr "}\n"
6422
6423   ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
6424
6425 (* Generate a list of function names, for debugging in the daemon.. *)
6426 and generate_daemon_names () =
6427   generate_header CStyle GPLv2plus;
6428
6429   pr "#include <config.h>\n";
6430   pr "\n";
6431   pr "#include \"daemon.h\"\n";
6432   pr "\n";
6433
6434   pr "/* This array is indexed by proc_nr.  See guestfs_protocol.x. */\n";
6435   pr "const char *function_names[] = {\n";
6436   List.iter (
6437     fun (name, _, proc_nr, _, _, _, _) -> pr "  [%d] = \"%s\",\n" proc_nr name
6438   ) daemon_functions;
6439   pr "};\n";
6440
6441 (* Generate the optional groups for the daemon to implement
6442  * guestfs_available.
6443  *)
6444 and generate_daemon_optgroups_c () =
6445   generate_header CStyle GPLv2plus;
6446
6447   pr "#include <config.h>\n";
6448   pr "\n";
6449   pr "#include \"daemon.h\"\n";
6450   pr "#include \"optgroups.h\"\n";
6451   pr "\n";
6452
6453   pr "struct optgroup optgroups[] = {\n";
6454   List.iter (
6455     fun (group, _) ->
6456       pr "  { \"%s\", optgroup_%s_available },\n" group group
6457   ) optgroups;
6458   pr "  { NULL, NULL }\n";
6459   pr "};\n"
6460
6461 and generate_daemon_optgroups_h () =
6462   generate_header CStyle GPLv2plus;
6463
6464   List.iter (
6465     fun (group, _) ->
6466       pr "extern int optgroup_%s_available (void);\n" group
6467   ) optgroups
6468
6469 (* Generate the tests. *)
6470 and generate_tests () =
6471   generate_header CStyle GPLv2plus;
6472
6473   pr "\
6474 #include <stdio.h>
6475 #include <stdlib.h>
6476 #include <string.h>
6477 #include <unistd.h>
6478 #include <sys/types.h>
6479 #include <fcntl.h>
6480
6481 #include \"guestfs.h\"
6482 #include \"guestfs-internal.h\"
6483
6484 static guestfs_h *g;
6485 static int suppress_error = 0;
6486
6487 static void print_error (guestfs_h *g, void *data, const char *msg)
6488 {
6489   if (!suppress_error)
6490     fprintf (stderr, \"%%s\\n\", msg);
6491 }
6492
6493 /* FIXME: nearly identical code appears in fish.c */
6494 static void print_strings (char *const *argv)
6495 {
6496   int argc;
6497
6498   for (argc = 0; argv[argc] != NULL; ++argc)
6499     printf (\"\\t%%s\\n\", argv[argc]);
6500 }
6501
6502 /*
6503 static void print_table (char const *const *argv)
6504 {
6505   int i;
6506
6507   for (i = 0; argv[i] != NULL; i += 2)
6508     printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
6509 }
6510 */
6511
6512 ";
6513
6514   (* Generate a list of commands which are not tested anywhere. *)
6515   pr "static void no_test_warnings (void)\n";
6516   pr "{\n";
6517
6518   let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
6519   List.iter (
6520     fun (_, _, _, _, tests, _, _) ->
6521       let tests = filter_map (
6522         function
6523         | (_, (Always|If _|Unless _), test) -> Some test
6524         | (_, Disabled, _) -> None
6525       ) tests in
6526       let seq = List.concat (List.map seq_of_test tests) in
6527       let cmds_tested = List.map List.hd seq in
6528       List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
6529   ) all_functions;
6530
6531   List.iter (
6532     fun (name, _, _, _, _, _, _) ->
6533       if not (Hashtbl.mem hash name) then
6534         pr "  fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
6535   ) all_functions;
6536
6537   pr "}\n";
6538   pr "\n";
6539
6540   (* Generate the actual tests.  Note that we generate the tests
6541    * in reverse order, deliberately, so that (in general) the
6542    * newest tests run first.  This makes it quicker and easier to
6543    * debug them.
6544    *)
6545   let test_names =
6546     List.map (
6547       fun (name, _, _, flags, tests, _, _) ->
6548         mapi (generate_one_test name flags) tests
6549     ) (List.rev all_functions) in
6550   let test_names = List.concat test_names in
6551   let nr_tests = List.length test_names in
6552
6553   pr "\
6554 int main (int argc, char *argv[])
6555 {
6556   char c = 0;
6557   unsigned long int n_failed = 0;
6558   const char *filename;
6559   int fd;
6560   int nr_tests, test_num = 0;
6561
6562   setbuf (stdout, NULL);
6563
6564   no_test_warnings ();
6565
6566   g = guestfs_create ();
6567   if (g == NULL) {
6568     printf (\"guestfs_create FAILED\\n\");
6569     exit (EXIT_FAILURE);
6570   }
6571
6572   guestfs_set_error_handler (g, print_error, NULL);
6573
6574   guestfs_set_path (g, \"../appliance\");
6575
6576   filename = \"test1.img\";
6577   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6578   if (fd == -1) {
6579     perror (filename);
6580     exit (EXIT_FAILURE);
6581   }
6582   if (lseek (fd, %d, SEEK_SET) == -1) {
6583     perror (\"lseek\");
6584     close (fd);
6585     unlink (filename);
6586     exit (EXIT_FAILURE);
6587   }
6588   if (write (fd, &c, 1) == -1) {
6589     perror (\"write\");
6590     close (fd);
6591     unlink (filename);
6592     exit (EXIT_FAILURE);
6593   }
6594   if (close (fd) == -1) {
6595     perror (filename);
6596     unlink (filename);
6597     exit (EXIT_FAILURE);
6598   }
6599   if (guestfs_add_drive (g, filename) == -1) {
6600     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6601     exit (EXIT_FAILURE);
6602   }
6603
6604   filename = \"test2.img\";
6605   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6606   if (fd == -1) {
6607     perror (filename);
6608     exit (EXIT_FAILURE);
6609   }
6610   if (lseek (fd, %d, SEEK_SET) == -1) {
6611     perror (\"lseek\");
6612     close (fd);
6613     unlink (filename);
6614     exit (EXIT_FAILURE);
6615   }
6616   if (write (fd, &c, 1) == -1) {
6617     perror (\"write\");
6618     close (fd);
6619     unlink (filename);
6620     exit (EXIT_FAILURE);
6621   }
6622   if (close (fd) == -1) {
6623     perror (filename);
6624     unlink (filename);
6625     exit (EXIT_FAILURE);
6626   }
6627   if (guestfs_add_drive (g, filename) == -1) {
6628     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6629     exit (EXIT_FAILURE);
6630   }
6631
6632   filename = \"test3.img\";
6633   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6634   if (fd == -1) {
6635     perror (filename);
6636     exit (EXIT_FAILURE);
6637   }
6638   if (lseek (fd, %d, SEEK_SET) == -1) {
6639     perror (\"lseek\");
6640     close (fd);
6641     unlink (filename);
6642     exit (EXIT_FAILURE);
6643   }
6644   if (write (fd, &c, 1) == -1) {
6645     perror (\"write\");
6646     close (fd);
6647     unlink (filename);
6648     exit (EXIT_FAILURE);
6649   }
6650   if (close (fd) == -1) {
6651     perror (filename);
6652     unlink (filename);
6653     exit (EXIT_FAILURE);
6654   }
6655   if (guestfs_add_drive (g, filename) == -1) {
6656     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6657     exit (EXIT_FAILURE);
6658   }
6659
6660   if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
6661     printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
6662     exit (EXIT_FAILURE);
6663   }
6664
6665   /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
6666   alarm (600);
6667
6668   if (guestfs_launch (g) == -1) {
6669     printf (\"guestfs_launch FAILED\\n\");
6670     exit (EXIT_FAILURE);
6671   }
6672
6673   /* Cancel previous alarm. */
6674   alarm (0);
6675
6676   nr_tests = %d;
6677
6678 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
6679
6680   iteri (
6681     fun i test_name ->
6682       pr "  test_num++;\n";
6683       pr "  printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
6684       pr "  if (%s () == -1) {\n" test_name;
6685       pr "    printf (\"%s FAILED\\n\");\n" test_name;
6686       pr "    n_failed++;\n";
6687       pr "  }\n";
6688   ) test_names;
6689   pr "\n";
6690
6691   pr "  guestfs_close (g);\n";
6692   pr "  unlink (\"test1.img\");\n";
6693   pr "  unlink (\"test2.img\");\n";
6694   pr "  unlink (\"test3.img\");\n";
6695   pr "\n";
6696
6697   pr "  if (n_failed > 0) {\n";
6698   pr "    printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
6699   pr "    exit (EXIT_FAILURE);\n";
6700   pr "  }\n";
6701   pr "\n";
6702
6703   pr "  exit (EXIT_SUCCESS);\n";
6704   pr "}\n"
6705
6706 and generate_one_test name flags i (init, prereq, test) =
6707   let test_name = sprintf "test_%s_%d" name i in
6708
6709   pr "\
6710 static int %s_skip (void)
6711 {
6712   const char *str;
6713
6714   str = getenv (\"TEST_ONLY\");
6715   if (str)
6716     return strstr (str, \"%s\") == NULL;
6717   str = getenv (\"SKIP_%s\");
6718   if (str && STREQ (str, \"1\")) return 1;
6719   str = getenv (\"SKIP_TEST_%s\");
6720   if (str && STREQ (str, \"1\")) return 1;
6721   return 0;
6722 }
6723
6724 " test_name name (String.uppercase test_name) (String.uppercase name);
6725
6726   (match prereq with
6727    | Disabled | Always -> ()
6728    | If code | Unless code ->
6729        pr "static int %s_prereq (void)\n" test_name;
6730        pr "{\n";
6731        pr "  %s\n" code;
6732        pr "}\n";
6733        pr "\n";
6734   );
6735
6736   pr "\
6737 static int %s (void)
6738 {
6739   if (%s_skip ()) {
6740     printf (\"        %%s skipped (reason: environment variable set)\\n\", \"%s\");
6741     return 0;
6742   }
6743
6744 " test_name test_name test_name;
6745
6746   (* Optional functions should only be tested if the relevant
6747    * support is available in the daemon.
6748    *)
6749   List.iter (
6750     function
6751     | Optional group ->
6752         pr "  {\n";
6753         pr "    const char *groups[] = { \"%s\", NULL };\n" group;
6754         pr "    int r;\n";
6755         pr "    suppress_error = 1;\n";
6756         pr "    r = guestfs_available (g, (char **) groups);\n";
6757         pr "    suppress_error = 0;\n";
6758         pr "    if (r == -1) {\n";
6759         pr "      printf (\"        %%s skipped (reason: group %%s not available in daemon)\\n\", \"%s\", groups[0]);\n" test_name;
6760         pr "      return 0;\n";
6761         pr "    }\n";
6762         pr "  }\n";
6763     | _ -> ()
6764   ) flags;
6765
6766   (match prereq with
6767    | Disabled ->
6768        pr "  printf (\"        %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
6769    | If _ ->
6770        pr "  if (! %s_prereq ()) {\n" test_name;
6771        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6772        pr "    return 0;\n";
6773        pr "  }\n";
6774        pr "\n";
6775        generate_one_test_body name i test_name init test;
6776    | Unless _ ->
6777        pr "  if (%s_prereq ()) {\n" test_name;
6778        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6779        pr "    return 0;\n";
6780        pr "  }\n";
6781        pr "\n";
6782        generate_one_test_body name i test_name init test;
6783    | Always ->
6784        generate_one_test_body name i test_name init test
6785   );
6786
6787   pr "  return 0;\n";
6788   pr "}\n";
6789   pr "\n";
6790   test_name
6791
6792 and generate_one_test_body name i test_name init test =
6793   (match init with
6794    | InitNone (* XXX at some point, InitNone and InitEmpty became
6795                * folded together as the same thing.  Really we should
6796                * make InitNone do nothing at all, but the tests may
6797                * need to be checked to make sure this is OK.
6798                *)
6799    | InitEmpty ->
6800        pr "  /* InitNone|InitEmpty for %s */\n" test_name;
6801        List.iter (generate_test_command_call test_name)
6802          [["blockdev_setrw"; "/dev/sda"];
6803           ["umount_all"];
6804           ["lvm_remove_all"]]
6805    | InitPartition ->
6806        pr "  /* InitPartition for %s: create /dev/sda1 */\n" test_name;
6807        List.iter (generate_test_command_call test_name)
6808          [["blockdev_setrw"; "/dev/sda"];
6809           ["umount_all"];
6810           ["lvm_remove_all"];
6811           ["part_disk"; "/dev/sda"; "mbr"]]
6812    | InitBasicFS ->
6813        pr "  /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
6814        List.iter (generate_test_command_call test_name)
6815          [["blockdev_setrw"; "/dev/sda"];
6816           ["umount_all"];
6817           ["lvm_remove_all"];
6818           ["part_disk"; "/dev/sda"; "mbr"];
6819           ["mkfs"; "ext2"; "/dev/sda1"];
6820           ["mount_options"; ""; "/dev/sda1"; "/"]]
6821    | InitBasicFSonLVM ->
6822        pr "  /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
6823          test_name;
6824        List.iter (generate_test_command_call test_name)
6825          [["blockdev_setrw"; "/dev/sda"];
6826           ["umount_all"];
6827           ["lvm_remove_all"];
6828           ["part_disk"; "/dev/sda"; "mbr"];
6829           ["pvcreate"; "/dev/sda1"];
6830           ["vgcreate"; "VG"; "/dev/sda1"];
6831           ["lvcreate"; "LV"; "VG"; "8"];
6832           ["mkfs"; "ext2"; "/dev/VG/LV"];
6833           ["mount_options"; ""; "/dev/VG/LV"; "/"]]
6834    | InitISOFS ->
6835        pr "  /* InitISOFS for %s */\n" test_name;
6836        List.iter (generate_test_command_call test_name)
6837          [["blockdev_setrw"; "/dev/sda"];
6838           ["umount_all"];
6839           ["lvm_remove_all"];
6840           ["mount_ro"; "/dev/sdd"; "/"]]
6841   );
6842
6843   let get_seq_last = function
6844     | [] ->
6845         failwithf "%s: you cannot use [] (empty list) when expecting a command"
6846           test_name
6847     | seq ->
6848         let seq = List.rev seq in
6849         List.rev (List.tl seq), List.hd seq
6850   in
6851
6852   match test with
6853   | TestRun seq ->
6854       pr "  /* TestRun for %s (%d) */\n" name i;
6855       List.iter (generate_test_command_call test_name) seq
6856   | TestOutput (seq, expected) ->
6857       pr "  /* TestOutput for %s (%d) */\n" name i;
6858       pr "  const char *expected = \"%s\";\n" (c_quote expected);
6859       let seq, last = get_seq_last seq in
6860       let test () =
6861         pr "    if (STRNEQ (r, expected)) {\n";
6862         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6863         pr "      return -1;\n";
6864         pr "    }\n"
6865       in
6866       List.iter (generate_test_command_call test_name) seq;
6867       generate_test_command_call ~test test_name last
6868   | TestOutputList (seq, expected) ->
6869       pr "  /* TestOutputList for %s (%d) */\n" name i;
6870       let seq, last = get_seq_last seq in
6871       let test () =
6872         iteri (
6873           fun i str ->
6874             pr "    if (!r[%d]) {\n" i;
6875             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6876             pr "      print_strings (r);\n";
6877             pr "      return -1;\n";
6878             pr "    }\n";
6879             pr "    {\n";
6880             pr "      const char *expected = \"%s\";\n" (c_quote str);
6881             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
6882             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6883             pr "        return -1;\n";
6884             pr "      }\n";
6885             pr "    }\n"
6886         ) expected;
6887         pr "    if (r[%d] != NULL) {\n" (List.length expected);
6888         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6889           test_name;
6890         pr "      print_strings (r);\n";
6891         pr "      return -1;\n";
6892         pr "    }\n"
6893       in
6894       List.iter (generate_test_command_call test_name) seq;
6895       generate_test_command_call ~test test_name last
6896   | TestOutputListOfDevices (seq, expected) ->
6897       pr "  /* TestOutputListOfDevices for %s (%d) */\n" name i;
6898       let seq, last = get_seq_last seq in
6899       let test () =
6900         iteri (
6901           fun i str ->
6902             pr "    if (!r[%d]) {\n" i;
6903             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6904             pr "      print_strings (r);\n";
6905             pr "      return -1;\n";
6906             pr "    }\n";
6907             pr "    {\n";
6908             pr "      const char *expected = \"%s\";\n" (c_quote str);
6909             pr "      r[%d][5] = 's';\n" i;
6910             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
6911             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6912             pr "        return -1;\n";
6913             pr "      }\n";
6914             pr "    }\n"
6915         ) expected;
6916         pr "    if (r[%d] != NULL) {\n" (List.length expected);
6917         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6918           test_name;
6919         pr "      print_strings (r);\n";
6920         pr "      return -1;\n";
6921         pr "    }\n"
6922       in
6923       List.iter (generate_test_command_call test_name) seq;
6924       generate_test_command_call ~test test_name last
6925   | TestOutputInt (seq, expected) ->
6926       pr "  /* TestOutputInt for %s (%d) */\n" name i;
6927       let seq, last = get_seq_last seq in
6928       let test () =
6929         pr "    if (r != %d) {\n" expected;
6930         pr "      fprintf (stderr, \"%s: expected %d but got %%d\\n\","
6931           test_name expected;
6932         pr "               (int) r);\n";
6933         pr "      return -1;\n";
6934         pr "    }\n"
6935       in
6936       List.iter (generate_test_command_call test_name) seq;
6937       generate_test_command_call ~test test_name last
6938   | TestOutputIntOp (seq, op, expected) ->
6939       pr "  /* TestOutputIntOp for %s (%d) */\n" name i;
6940       let seq, last = get_seq_last seq in
6941       let test () =
6942         pr "    if (! (r %s %d)) {\n" op expected;
6943         pr "      fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
6944           test_name op expected;
6945         pr "               (int) r);\n";
6946         pr "      return -1;\n";
6947         pr "    }\n"
6948       in
6949       List.iter (generate_test_command_call test_name) seq;
6950       generate_test_command_call ~test test_name last
6951   | TestOutputTrue seq ->
6952       pr "  /* TestOutputTrue for %s (%d) */\n" name i;
6953       let seq, last = get_seq_last seq in
6954       let test () =
6955         pr "    if (!r) {\n";
6956         pr "      fprintf (stderr, \"%s: expected true, got false\\n\");\n"
6957           test_name;
6958         pr "      return -1;\n";
6959         pr "    }\n"
6960       in
6961       List.iter (generate_test_command_call test_name) seq;
6962       generate_test_command_call ~test test_name last
6963   | TestOutputFalse seq ->
6964       pr "  /* TestOutputFalse for %s (%d) */\n" name i;
6965       let seq, last = get_seq_last seq in
6966       let test () =
6967         pr "    if (r) {\n";
6968         pr "      fprintf (stderr, \"%s: expected false, got true\\n\");\n"
6969           test_name;
6970         pr "      return -1;\n";
6971         pr "    }\n"
6972       in
6973       List.iter (generate_test_command_call test_name) seq;
6974       generate_test_command_call ~test test_name last
6975   | TestOutputLength (seq, expected) ->
6976       pr "  /* TestOutputLength for %s (%d) */\n" name i;
6977       let seq, last = get_seq_last seq in
6978       let test () =
6979         pr "    int j;\n";
6980         pr "    for (j = 0; j < %d; ++j)\n" expected;
6981         pr "      if (r[j] == NULL) {\n";
6982         pr "        fprintf (stderr, \"%s: short list returned\\n\");\n"
6983           test_name;
6984         pr "        print_strings (r);\n";
6985         pr "        return -1;\n";
6986         pr "      }\n";
6987         pr "    if (r[j] != NULL) {\n";
6988         pr "      fprintf (stderr, \"%s: long list returned\\n\");\n"
6989           test_name;
6990         pr "      print_strings (r);\n";
6991         pr "      return -1;\n";
6992         pr "    }\n"
6993       in
6994       List.iter (generate_test_command_call test_name) seq;
6995       generate_test_command_call ~test test_name last
6996   | TestOutputBuffer (seq, expected) ->
6997       pr "  /* TestOutputBuffer for %s (%d) */\n" name i;
6998       pr "  const char *expected = \"%s\";\n" (c_quote expected);
6999       let seq, last = get_seq_last seq in
7000       let len = String.length expected in
7001       let test () =
7002         pr "    if (size != %d) {\n" len;
7003         pr "      fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
7004         pr "      return -1;\n";
7005         pr "    }\n";
7006         pr "    if (STRNEQLEN (r, expected, size)) {\n";
7007         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
7008         pr "      return -1;\n";
7009         pr "    }\n"
7010       in
7011       List.iter (generate_test_command_call test_name) seq;
7012       generate_test_command_call ~test test_name last
7013   | TestOutputStruct (seq, checks) ->
7014       pr "  /* TestOutputStruct for %s (%d) */\n" name i;
7015       let seq, last = get_seq_last seq in
7016       let test () =
7017         List.iter (
7018           function
7019           | CompareWithInt (field, expected) ->
7020               pr "    if (r->%s != %d) {\n" field expected;
7021               pr "      fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
7022                 test_name field expected;
7023               pr "               (int) r->%s);\n" field;
7024               pr "      return -1;\n";
7025               pr "    }\n"
7026           | CompareWithIntOp (field, op, expected) ->
7027               pr "    if (!(r->%s %s %d)) {\n" field op expected;
7028               pr "      fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
7029                 test_name field op expected;
7030               pr "               (int) r->%s);\n" field;
7031               pr "      return -1;\n";
7032               pr "    }\n"
7033           | CompareWithString (field, expected) ->
7034               pr "    if (STRNEQ (r->%s, \"%s\")) {\n" field expected;
7035               pr "      fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
7036                 test_name field expected;
7037               pr "               r->%s);\n" field;
7038               pr "      return -1;\n";
7039               pr "    }\n"
7040           | CompareFieldsIntEq (field1, field2) ->
7041               pr "    if (r->%s != r->%s) {\n" field1 field2;
7042               pr "      fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
7043                 test_name field1 field2;
7044               pr "               (int) r->%s, (int) r->%s);\n" field1 field2;
7045               pr "      return -1;\n";
7046               pr "    }\n"
7047           | CompareFieldsStrEq (field1, field2) ->
7048               pr "    if (STRNEQ (r->%s, r->%s)) {\n" field1 field2;
7049               pr "      fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
7050                 test_name field1 field2;
7051               pr "               r->%s, r->%s);\n" field1 field2;
7052               pr "      return -1;\n";
7053               pr "    }\n"
7054         ) checks
7055       in
7056       List.iter (generate_test_command_call test_name) seq;
7057       generate_test_command_call ~test test_name last
7058   | TestLastFail seq ->
7059       pr "  /* TestLastFail for %s (%d) */\n" name i;
7060       let seq, last = get_seq_last seq in
7061       List.iter (generate_test_command_call test_name) seq;
7062       generate_test_command_call test_name ~expect_error:true last
7063
7064 (* Generate the code to run a command, leaving the result in 'r'.
7065  * If you expect to get an error then you should set expect_error:true.
7066  *)
7067 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
7068   match cmd with
7069   | [] -> assert false
7070   | name :: args ->
7071       (* Look up the command to find out what args/ret it has. *)
7072       let style =
7073         try
7074           let _, style, _, _, _, _, _ =
7075             List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
7076           style
7077         with Not_found ->
7078           failwithf "%s: in test, command %s was not found" test_name name in
7079
7080       if List.length (snd style) <> List.length args then
7081         failwithf "%s: in test, wrong number of args given to %s"
7082           test_name name;
7083
7084       pr "  {\n";
7085
7086       List.iter (
7087         function
7088         | OptString n, "NULL" -> ()
7089         | Pathname n, arg
7090         | Device n, arg
7091         | Dev_or_Path n, arg
7092         | String n, arg
7093         | OptString n, arg ->
7094             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
7095         | Int _, _
7096         | Int64 _, _
7097         | Bool _, _
7098         | FileIn _, _ | FileOut _, _ -> ()
7099         | StringList n, "" | DeviceList n, "" ->
7100             pr "    const char *const %s[1] = { NULL };\n" n
7101         | StringList n, arg | DeviceList n, arg ->
7102             let strs = string_split " " arg in
7103             iteri (
7104               fun i str ->
7105                 pr "    const char *%s_%d = \"%s\";\n" n i (c_quote str);
7106             ) strs;
7107             pr "    const char *const %s[] = {\n" n;
7108             iteri (
7109               fun i _ -> pr "      %s_%d,\n" n i
7110             ) strs;
7111             pr "      NULL\n";
7112             pr "    };\n";
7113       ) (List.combine (snd style) args);
7114
7115       let error_code =
7116         match fst style with
7117         | RErr | RInt _ | RBool _ -> pr "    int r;\n"; "-1"
7118         | RInt64 _ -> pr "    int64_t r;\n"; "-1"
7119         | RConstString _ | RConstOptString _ ->
7120             pr "    const char *r;\n"; "NULL"
7121         | RString _ -> pr "    char *r;\n"; "NULL"
7122         | RStringList _ | RHashtable _ ->
7123             pr "    char **r;\n";
7124             pr "    int i;\n";
7125             "NULL"
7126         | RStruct (_, typ) ->
7127             pr "    struct guestfs_%s *r;\n" typ; "NULL"
7128         | RStructList (_, typ) ->
7129             pr "    struct guestfs_%s_list *r;\n" typ; "NULL"
7130         | RBufferOut _ ->
7131             pr "    char *r;\n";
7132             pr "    size_t size;\n";
7133             "NULL" in
7134
7135       pr "    suppress_error = %d;\n" (if expect_error then 1 else 0);
7136       pr "    r = guestfs_%s (g" name;
7137
7138       (* Generate the parameters. *)
7139       List.iter (
7140         function
7141         | OptString _, "NULL" -> pr ", NULL"
7142         | Pathname n, _
7143         | Device n, _ | Dev_or_Path n, _
7144         | String n, _
7145         | OptString n, _ ->
7146             pr ", %s" n
7147         | FileIn _, arg | FileOut _, arg ->
7148             pr ", \"%s\"" (c_quote arg)
7149         | StringList n, _ | DeviceList n, _ ->
7150             pr ", (char **) %s" n
7151         | Int _, arg ->
7152             let i =
7153               try int_of_string arg
7154               with Failure "int_of_string" ->
7155                 failwithf "%s: expecting an int, but got '%s'" test_name arg in
7156             pr ", %d" i
7157         | Int64 _, arg ->
7158             let i =
7159               try Int64.of_string arg
7160               with Failure "int_of_string" ->
7161                 failwithf "%s: expecting an int64, but got '%s'" test_name arg in
7162             pr ", %Ld" i
7163         | Bool _, arg ->
7164             let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
7165       ) (List.combine (snd style) args);
7166
7167       (match fst style with
7168        | RBufferOut _ -> pr ", &size"
7169        | _ -> ()
7170       );
7171
7172       pr ");\n";
7173
7174       if not expect_error then
7175         pr "    if (r == %s)\n" error_code
7176       else
7177         pr "    if (r != %s)\n" error_code;
7178       pr "      return -1;\n";
7179
7180       (* Insert the test code. *)
7181       (match test with
7182        | None -> ()
7183        | Some f -> f ()
7184       );
7185
7186       (match fst style with
7187        | RErr | RInt _ | RInt64 _ | RBool _
7188        | RConstString _ | RConstOptString _ -> ()
7189        | RString _ | RBufferOut _ -> pr "    free (r);\n"
7190        | RStringList _ | RHashtable _ ->
7191            pr "    for (i = 0; r[i] != NULL; ++i)\n";
7192            pr "      free (r[i]);\n";
7193            pr "    free (r);\n"
7194        | RStruct (_, typ) ->
7195            pr "    guestfs_free_%s (r);\n" typ
7196        | RStructList (_, typ) ->
7197            pr "    guestfs_free_%s_list (r);\n" typ
7198       );
7199
7200       pr "  }\n"
7201
7202 and c_quote str =
7203   let str = replace_str str "\r" "\\r" in
7204   let str = replace_str str "\n" "\\n" in
7205   let str = replace_str str "\t" "\\t" in
7206   let str = replace_str str "\000" "\\0" in
7207   str
7208
7209 (* Generate a lot of different functions for guestfish. *)
7210 and generate_fish_cmds () =
7211   generate_header CStyle GPLv2plus;
7212
7213   let all_functions =
7214     List.filter (
7215       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7216     ) all_functions in
7217   let all_functions_sorted =
7218     List.filter (
7219       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7220     ) all_functions_sorted in
7221
7222   pr "#include <config.h>\n";
7223   pr "\n";
7224   pr "#include <stdio.h>\n";
7225   pr "#include <stdlib.h>\n";
7226   pr "#include <string.h>\n";
7227   pr "#include <inttypes.h>\n";
7228   pr "\n";
7229   pr "#include <guestfs.h>\n";
7230   pr "#include \"c-ctype.h\"\n";
7231   pr "#include \"full-write.h\"\n";
7232   pr "#include \"xstrtol.h\"\n";
7233   pr "#include \"fish.h\"\n";
7234   pr "\n";
7235
7236   (* list_commands function, which implements guestfish -h *)
7237   pr "void list_commands (void)\n";
7238   pr "{\n";
7239   pr "  printf (\"    %%-16s     %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
7240   pr "  list_builtin_commands ();\n";
7241   List.iter (
7242     fun (name, _, _, flags, _, shortdesc, _) ->
7243       let name = replace_char name '_' '-' in
7244       pr "  printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
7245         name shortdesc
7246   ) all_functions_sorted;
7247   pr "  printf (\"    %%s\\n\",";
7248   pr "          _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
7249   pr "}\n";
7250   pr "\n";
7251
7252   (* display_command function, which implements guestfish -h cmd *)
7253   pr "void display_command (const char *cmd)\n";
7254   pr "{\n";
7255   List.iter (
7256     fun (name, style, _, flags, _, shortdesc, longdesc) ->
7257       let name2 = replace_char name '_' '-' in
7258       let alias =
7259         try find_map (function FishAlias n -> Some n | _ -> None) flags
7260         with Not_found -> name in
7261       let longdesc = replace_str longdesc "C<guestfs_" "C<" in
7262       let synopsis =
7263         match snd style with
7264         | [] -> name2
7265         | args ->
7266             sprintf "%s %s"
7267               name2 (String.concat " " (List.map name_of_argt args)) in
7268
7269       let warnings =
7270         if List.mem ProtocolLimitWarning flags then
7271           ("\n\n" ^ protocol_limit_warning)
7272         else "" in
7273
7274       (* For DangerWillRobinson commands, we should probably have
7275        * guestfish prompt before allowing you to use them (especially
7276        * in interactive mode). XXX
7277        *)
7278       let warnings =
7279         warnings ^
7280           if List.mem DangerWillRobinson flags then
7281             ("\n\n" ^ danger_will_robinson)
7282           else "" in
7283
7284       let warnings =
7285         warnings ^
7286           match deprecation_notice flags with
7287           | None -> ""
7288           | Some txt -> "\n\n" ^ txt in
7289
7290       let describe_alias =
7291         if name <> alias then
7292           sprintf "\n\nYou can use '%s' as an alias for this command." alias
7293         else "" in
7294
7295       pr "  if (";
7296       pr "STRCASEEQ (cmd, \"%s\")" name;
7297       if name <> name2 then
7298         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7299       if name <> alias then
7300         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7301       pr ")\n";
7302       pr "    pod2text (\"%s\", _(\"%s\"), %S);\n"
7303         name2 shortdesc
7304         ("=head1 SYNOPSIS\n\n " ^ synopsis ^ "\n\n" ^
7305          "=head1 DESCRIPTION\n\n" ^
7306          longdesc ^ warnings ^ describe_alias);
7307       pr "  else\n"
7308   ) all_functions;
7309   pr "    display_builtin_command (cmd);\n";
7310   pr "}\n";
7311   pr "\n";
7312
7313   let emit_print_list_function typ =
7314     pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
7315       typ typ typ;
7316     pr "{\n";
7317     pr "  unsigned int i;\n";
7318     pr "\n";
7319     pr "  for (i = 0; i < %ss->len; ++i) {\n" typ;
7320     pr "    printf (\"[%%d] = {\\n\", i);\n";
7321     pr "    print_%s_indent (&%ss->val[i], \"  \");\n" typ typ;
7322     pr "    printf (\"}\\n\");\n";
7323     pr "  }\n";
7324     pr "}\n";
7325     pr "\n";
7326   in
7327
7328   (* print_* functions *)
7329   List.iter (
7330     fun (typ, cols) ->
7331       let needs_i =
7332         List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
7333
7334       pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
7335       pr "{\n";
7336       if needs_i then (
7337         pr "  unsigned int i;\n";
7338         pr "\n"
7339       );
7340       List.iter (
7341         function
7342         | name, FString ->
7343             pr "  printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
7344         | name, FUUID ->
7345             pr "  printf (\"%%s%s: \", indent);\n" name;
7346             pr "  for (i = 0; i < 32; ++i)\n";
7347             pr "    printf (\"%%c\", %s->%s[i]);\n" typ name;
7348             pr "  printf (\"\\n\");\n"
7349         | name, FBuffer ->
7350             pr "  printf (\"%%s%s: \", indent);\n" name;
7351             pr "  for (i = 0; i < %s->%s_len; ++i)\n" typ name;
7352             pr "    if (c_isprint (%s->%s[i]))\n" typ name;
7353             pr "      printf (\"%%c\", %s->%s[i]);\n" typ name;
7354             pr "    else\n";
7355             pr "      printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
7356             pr "  printf (\"\\n\");\n"
7357         | name, (FUInt64|FBytes) ->
7358             pr "  printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
7359               name typ name
7360         | name, FInt64 ->
7361             pr "  printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
7362               name typ name
7363         | name, FUInt32 ->
7364             pr "  printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
7365               name typ name
7366         | name, FInt32 ->
7367             pr "  printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
7368               name typ name
7369         | name, FChar ->
7370             pr "  printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
7371               name typ name
7372         | name, FOptPercent ->
7373             pr "  if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
7374               typ name name typ name;
7375             pr "  else printf (\"%%s%s: \\n\", indent);\n" name
7376       ) cols;
7377       pr "}\n";
7378       pr "\n";
7379   ) structs;
7380
7381   (* Emit a print_TYPE_list function definition only if that function is used. *)
7382   List.iter (
7383     function
7384     | typ, (RStructListOnly | RStructAndList) ->
7385         (* generate the function for typ *)
7386         emit_print_list_function typ
7387     | typ, _ -> () (* empty *)
7388   ) (rstructs_used_by all_functions);
7389
7390   (* Emit a print_TYPE function definition only if that function is used. *)
7391   List.iter (
7392     function
7393     | typ, (RStructOnly | RStructAndList) ->
7394         pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
7395         pr "{\n";
7396         pr "  print_%s_indent (%s, \"\");\n" typ typ;
7397         pr "}\n";
7398         pr "\n";
7399     | typ, _ -> () (* empty *)
7400   ) (rstructs_used_by all_functions);
7401
7402   (* run_<action> actions *)
7403   List.iter (
7404     fun (name, style, _, flags, _, _, _) ->
7405       pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
7406       pr "{\n";
7407       (match fst style with
7408        | RErr
7409        | RInt _
7410        | RBool _ -> pr "  int r;\n"
7411        | RInt64 _ -> pr "  int64_t r;\n"
7412        | RConstString _ | RConstOptString _ -> pr "  const char *r;\n"
7413        | RString _ -> pr "  char *r;\n"
7414        | RStringList _ | RHashtable _ -> pr "  char **r;\n"
7415        | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ
7416        | RStructList (_, typ) -> pr "  struct guestfs_%s_list *r;\n" typ
7417        | RBufferOut _ ->
7418            pr "  char *r;\n";
7419            pr "  size_t size;\n";
7420       );
7421       List.iter (
7422         function
7423         | Device n
7424         | String n
7425         | OptString n -> pr "  const char *%s;\n" n
7426         | Pathname n
7427         | Dev_or_Path n
7428         | FileIn n
7429         | FileOut n -> pr "  char *%s;\n" n
7430         | StringList n | DeviceList n -> pr "  char **%s;\n" n
7431         | Bool n -> pr "  int %s;\n" n
7432         | Int n -> pr "  int %s;\n" n
7433         | Int64 n -> pr "  int64_t %s;\n" n
7434       ) (snd style);
7435
7436       (* Check and convert parameters. *)
7437       let argc_expected = List.length (snd style) in
7438       pr "  if (argc != %d) {\n" argc_expected;
7439       pr "    fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
7440         argc_expected;
7441       pr "    fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
7442       pr "    return -1;\n";
7443       pr "  }\n";
7444
7445       let parse_integer fn fntyp rtyp range name i =
7446         pr "  {\n";
7447         pr "    strtol_error xerr;\n";
7448         pr "    %s r;\n" fntyp;
7449         pr "\n";
7450         pr "    xerr = %s (argv[%d], NULL, 0, &r, \"\");\n" fn i;
7451         pr "    if (xerr != LONGINT_OK) {\n";
7452         pr "      fprintf (stderr,\n";
7453         pr "               _(\"%%s: %%s: invalid integer parameter (%%s returned %%d)\\n\"),\n";
7454         pr "               cmd, \"%s\", \"%s\", xerr);\n" name fn;
7455         pr "      return -1;\n";
7456         pr "    }\n";
7457         (match range with
7458          | None -> ()
7459          | Some (min, max, comment) ->
7460              pr "    /* %s */\n" comment;
7461              pr "    if (r < %s || r > %s) {\n" min max;
7462              pr "      fprintf (stderr, _(\"%%s: %%s: integer out of range\\n\"), cmd, \"%s\");\n"
7463                name;
7464              pr "      return -1;\n";
7465              pr "    }\n";
7466              pr "    /* The check above should ensure this assignment does not overflow. */\n";
7467         );
7468         pr "    %s = r;\n" name;
7469         pr "  }\n";
7470       in
7471
7472       iteri (
7473         fun i ->
7474           function
7475           | Device name
7476           | String name ->
7477               pr "  %s = argv[%d];\n" name i
7478           | Pathname name
7479           | Dev_or_Path name ->
7480               pr "  %s = resolve_win_path (argv[%d]);\n" name i;
7481               pr "  if (%s == NULL) return -1;\n" name
7482           | OptString name ->
7483               pr "  %s = STRNEQ (argv[%d], \"\") ? argv[%d] : NULL;\n"
7484                 name i i
7485           | FileIn name ->
7486               pr "  %s = file_in (argv[%d]);\n" name i;
7487               pr "  if (%s == NULL) return -1;\n" name
7488           | FileOut name ->
7489               pr "  %s = file_out (argv[%d]);\n" name i;
7490               pr "  if (%s == NULL) return -1;\n" name
7491           | StringList name | DeviceList name ->
7492               pr "  %s = parse_string_list (argv[%d]);\n" name i;
7493               pr "  if (%s == NULL) return -1;\n" name;
7494           | Bool name ->
7495               pr "  %s = is_true (argv[%d]) ? 1 : 0;\n" name i
7496           | Int name ->
7497               let range =
7498                 let min = "(-(2LL<<30))"
7499                 and max = "((2LL<<30)-1)"
7500                 and comment =
7501                   "The Int type in the generator is a signed 31 bit int." in
7502                 Some (min, max, comment) in
7503               parse_integer "xstrtoll" "long long" "int" range name i
7504           | Int64 name ->
7505               parse_integer "xstrtoll" "long long" "int64_t" None name i
7506       ) (snd style);
7507
7508       (* Call C API function. *)
7509       let fn =
7510         try find_map (function FishAction n -> Some n | _ -> None) flags
7511         with Not_found -> sprintf "guestfs_%s" name in
7512       pr "  r = %s " fn;
7513       generate_c_call_args ~handle:"g" style;
7514       pr ";\n";
7515
7516       List.iter (
7517         function
7518         | Device name | String name
7519         | OptString name | Bool name
7520         | Int name | Int64 name -> ()
7521         | Pathname name | Dev_or_Path name | FileOut name ->
7522             pr "  free (%s);\n" name
7523         | FileIn name ->
7524             pr "  free_file_in (%s);\n" name
7525         | StringList name | DeviceList name ->
7526             pr "  free_strings (%s);\n" name
7527       ) (snd style);
7528
7529       (* Any output flags? *)
7530       let fish_output =
7531         let flags = filter_map (
7532           function FishOutput flag -> Some flag | _ -> None
7533         ) flags in
7534         match flags with
7535         | [] -> None
7536         | [f] -> Some f
7537         | _ ->
7538             failwithf "%s: more than one FishOutput flag is not allowed" name in
7539
7540       (* Check return value for errors and display command results. *)
7541       (match fst style with
7542        | RErr -> pr "  return r;\n"
7543        | RInt _ ->
7544            pr "  if (r == -1) return -1;\n";
7545            (match fish_output with
7546             | None ->
7547                 pr "  printf (\"%%d\\n\", r);\n";
7548             | Some FishOutputOctal ->
7549                 pr "  printf (\"%%s%%o\\n\", r != 0 ? \"0\" : \"\", r);\n";
7550             | Some FishOutputHexadecimal ->
7551                 pr "  printf (\"%%s%%x\\n\", r != 0 ? \"0x\" : \"\", r);\n");
7552            pr "  return 0;\n"
7553        | RInt64 _ ->
7554            pr "  if (r == -1) return -1;\n";
7555            (match fish_output with
7556             | None ->
7557                 pr "  printf (\"%%\" PRIi64 \"\\n\", r);\n";
7558             | Some FishOutputOctal ->
7559                 pr "  printf (\"%%s%%\" PRIo64 \"\\n\", r != 0 ? \"0\" : \"\", r);\n";
7560             | Some FishOutputHexadecimal ->
7561                 pr "  printf (\"%%s%%\" PRIx64 \"\\n\", r != 0 ? \"0x\" : \"\", r);\n");
7562            pr "  return 0;\n"
7563        | RBool _ ->
7564            pr "  if (r == -1) return -1;\n";
7565            pr "  if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
7566            pr "  return 0;\n"
7567        | RConstString _ ->
7568            pr "  if (r == NULL) return -1;\n";
7569            pr "  printf (\"%%s\\n\", r);\n";
7570            pr "  return 0;\n"
7571        | RConstOptString _ ->
7572            pr "  printf (\"%%s\\n\", r ? : \"(null)\");\n";
7573            pr "  return 0;\n"
7574        | RString _ ->
7575            pr "  if (r == NULL) return -1;\n";
7576            pr "  printf (\"%%s\\n\", r);\n";
7577            pr "  free (r);\n";
7578            pr "  return 0;\n"
7579        | RStringList _ ->
7580            pr "  if (r == NULL) return -1;\n";
7581            pr "  print_strings (r);\n";
7582            pr "  free_strings (r);\n";
7583            pr "  return 0;\n"
7584        | RStruct (_, typ) ->
7585            pr "  if (r == NULL) return -1;\n";
7586            pr "  print_%s (r);\n" typ;
7587            pr "  guestfs_free_%s (r);\n" typ;
7588            pr "  return 0;\n"
7589        | RStructList (_, typ) ->
7590            pr "  if (r == NULL) return -1;\n";
7591            pr "  print_%s_list (r);\n" typ;
7592            pr "  guestfs_free_%s_list (r);\n" typ;
7593            pr "  return 0;\n"
7594        | RHashtable _ ->
7595            pr "  if (r == NULL) return -1;\n";
7596            pr "  print_table (r);\n";
7597            pr "  free_strings (r);\n";
7598            pr "  return 0;\n"
7599        | RBufferOut _ ->
7600            pr "  if (r == NULL) return -1;\n";
7601            pr "  if (full_write (1, r, size) != size) {\n";
7602            pr "    perror (\"write\");\n";
7603            pr "    free (r);\n";
7604            pr "    return -1;\n";
7605            pr "  }\n";
7606            pr "  free (r);\n";
7607            pr "  return 0;\n"
7608       );
7609       pr "}\n";
7610       pr "\n"
7611   ) all_functions;
7612
7613   (* run_action function *)
7614   pr "int run_action (const char *cmd, int argc, char *argv[])\n";
7615   pr "{\n";
7616   List.iter (
7617     fun (name, _, _, flags, _, _, _) ->
7618       let name2 = replace_char name '_' '-' in
7619       let alias =
7620         try find_map (function FishAlias n -> Some n | _ -> None) flags
7621         with Not_found -> name in
7622       pr "  if (";
7623       pr "STRCASEEQ (cmd, \"%s\")" name;
7624       if name <> name2 then
7625         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7626       if name <> alias then
7627         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7628       pr ")\n";
7629       pr "    return run_%s (cmd, argc, argv);\n" name;
7630       pr "  else\n";
7631   ) all_functions;
7632   pr "    {\n";
7633   pr "      fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
7634   pr "      if (command_num == 1)\n";
7635   pr "        extended_help_message ();\n";
7636   pr "      return -1;\n";
7637   pr "    }\n";
7638   pr "  return 0;\n";
7639   pr "}\n";
7640   pr "\n"
7641
7642 (* Readline completion for guestfish. *)
7643 and generate_fish_completion () =
7644   generate_header CStyle GPLv2plus;
7645
7646   let all_functions =
7647     List.filter (
7648       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7649     ) all_functions in
7650
7651   pr "\
7652 #include <config.h>
7653
7654 #include <stdio.h>
7655 #include <stdlib.h>
7656 #include <string.h>
7657
7658 #ifdef HAVE_LIBREADLINE
7659 #include <readline/readline.h>
7660 #endif
7661
7662 #include \"fish.h\"
7663
7664 #ifdef HAVE_LIBREADLINE
7665
7666 static const char *const commands[] = {
7667   BUILTIN_COMMANDS_FOR_COMPLETION,
7668 ";
7669
7670   (* Get the commands, including the aliases.  They don't need to be
7671    * sorted - the generator() function just does a dumb linear search.
7672    *)
7673   let commands =
7674     List.map (
7675       fun (name, _, _, flags, _, _, _) ->
7676         let name2 = replace_char name '_' '-' in
7677         let alias =
7678           try find_map (function FishAlias n -> Some n | _ -> None) flags
7679           with Not_found -> name in
7680
7681         if name <> alias then [name2; alias] else [name2]
7682     ) all_functions in
7683   let commands = List.flatten commands in
7684
7685   List.iter (pr "  \"%s\",\n") commands;
7686
7687   pr "  NULL
7688 };
7689
7690 static char *
7691 generator (const char *text, int state)
7692 {
7693   static int index, len;
7694   const char *name;
7695
7696   if (!state) {
7697     index = 0;
7698     len = strlen (text);
7699   }
7700
7701   rl_attempted_completion_over = 1;
7702
7703   while ((name = commands[index]) != NULL) {
7704     index++;
7705     if (STRCASEEQLEN (name, text, len))
7706       return strdup (name);
7707   }
7708
7709   return NULL;
7710 }
7711
7712 #endif /* HAVE_LIBREADLINE */
7713
7714 #ifdef HAVE_RL_COMPLETION_MATCHES
7715 #define RL_COMPLETION_MATCHES rl_completion_matches
7716 #else
7717 #ifdef HAVE_COMPLETION_MATCHES
7718 #define RL_COMPLETION_MATCHES completion_matches
7719 #endif
7720 #endif /* else just fail if we don't have either symbol */
7721
7722 char **
7723 do_completion (const char *text, int start, int end)
7724 {
7725   char **matches = NULL;
7726
7727 #ifdef HAVE_LIBREADLINE
7728   rl_completion_append_character = ' ';
7729
7730   if (start == 0)
7731     matches = RL_COMPLETION_MATCHES (text, generator);
7732   else if (complete_dest_paths)
7733     matches = RL_COMPLETION_MATCHES (text, complete_dest_paths_generator);
7734 #endif
7735
7736   return matches;
7737 }
7738 ";
7739
7740 (* Generate the POD documentation for guestfish. *)
7741 and generate_fish_actions_pod () =
7742   let all_functions_sorted =
7743     List.filter (
7744       fun (_, _, _, flags, _, _, _) ->
7745         not (List.mem NotInFish flags || List.mem NotInDocs flags)
7746     ) all_functions_sorted in
7747
7748   let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
7749
7750   List.iter (
7751     fun (name, style, _, flags, _, _, longdesc) ->
7752       let longdesc =
7753         Str.global_substitute rex (
7754           fun s ->
7755             let sub =
7756               try Str.matched_group 1 s
7757               with Not_found ->
7758                 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
7759             "C<" ^ replace_char sub '_' '-' ^ ">"
7760         ) longdesc in
7761       let name = replace_char name '_' '-' in
7762       let alias =
7763         try find_map (function FishAlias n -> Some n | _ -> None) flags
7764         with Not_found -> name in
7765
7766       pr "=head2 %s" name;
7767       if name <> alias then
7768         pr " | %s" alias;
7769       pr "\n";
7770       pr "\n";
7771       pr " %s" name;
7772       List.iter (
7773         function
7774         | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
7775         | OptString n -> pr " %s" n
7776         | StringList n | DeviceList n -> pr " '%s ...'" n
7777         | Bool _ -> pr " true|false"
7778         | Int n -> pr " %s" n
7779         | Int64 n -> pr " %s" n
7780         | FileIn n | FileOut n -> pr " (%s|-)" n
7781       ) (snd style);
7782       pr "\n";
7783       pr "\n";
7784       pr "%s\n\n" longdesc;
7785
7786       if List.exists (function FileIn _ | FileOut _ -> true
7787                       | _ -> false) (snd style) then
7788         pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
7789
7790       if List.mem ProtocolLimitWarning flags then
7791         pr "%s\n\n" protocol_limit_warning;
7792
7793       if List.mem DangerWillRobinson flags then
7794         pr "%s\n\n" danger_will_robinson;
7795
7796       match deprecation_notice flags with
7797       | None -> ()
7798       | Some txt -> pr "%s\n\n" txt
7799   ) all_functions_sorted
7800
7801 (* Generate a C function prototype. *)
7802 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
7803     ?(single_line = false) ?(newline = false) ?(in_daemon = false)
7804     ?(prefix = "")
7805     ?handle name style =
7806   if extern then pr "extern ";
7807   if static then pr "static ";
7808   (match fst style with
7809    | RErr -> pr "int "
7810    | RInt _ -> pr "int "
7811    | RInt64 _ -> pr "int64_t "
7812    | RBool _ -> pr "int "
7813    | RConstString _ | RConstOptString _ -> pr "const char *"
7814    | RString _ | RBufferOut _ -> pr "char *"
7815    | RStringList _ | RHashtable _ -> pr "char **"
7816    | RStruct (_, typ) ->
7817        if not in_daemon then pr "struct guestfs_%s *" typ
7818        else pr "guestfs_int_%s *" typ
7819    | RStructList (_, typ) ->
7820        if not in_daemon then pr "struct guestfs_%s_list *" typ
7821        else pr "guestfs_int_%s_list *" typ
7822   );
7823   let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
7824   pr "%s%s (" prefix name;
7825   if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
7826     pr "void"
7827   else (
7828     let comma = ref false in
7829     (match handle with
7830      | None -> ()
7831      | Some handle -> pr "guestfs_h *%s" handle; comma := true
7832     );
7833     let next () =
7834       if !comma then (
7835         if single_line then pr ", " else pr ",\n\t\t"
7836       );
7837       comma := true
7838     in
7839     List.iter (
7840       function
7841       | Pathname n
7842       | Device n | Dev_or_Path n
7843       | String n
7844       | OptString n ->
7845           next ();
7846           pr "const char *%s" n
7847       | StringList n | DeviceList n ->
7848           next ();
7849           pr "char *const *%s" n
7850       | Bool n -> next (); pr "int %s" n
7851       | Int n -> next (); pr "int %s" n
7852       | Int64 n -> next (); pr "int64_t %s" n
7853       | FileIn n
7854       | FileOut n ->
7855           if not in_daemon then (next (); pr "const char *%s" n)
7856     ) (snd style);
7857     if is_RBufferOut then (next (); pr "size_t *size_r");
7858   );
7859   pr ")";
7860   if semicolon then pr ";";
7861   if newline then pr "\n"
7862
7863 (* Generate C call arguments, eg "(handle, foo, bar)" *)
7864 and generate_c_call_args ?handle ?(decl = false) style =
7865   pr "(";
7866   let comma = ref false in
7867   let next () =
7868     if !comma then pr ", ";
7869     comma := true
7870   in
7871   (match handle with
7872    | None -> ()
7873    | Some handle -> pr "%s" handle; comma := true
7874   );
7875   List.iter (
7876     fun arg ->
7877       next ();
7878       pr "%s" (name_of_argt arg)
7879   ) (snd style);
7880   (* For RBufferOut calls, add implicit &size parameter. *)
7881   if not decl then (
7882     match fst style with
7883     | RBufferOut _ ->
7884         next ();
7885         pr "&size"
7886     | _ -> ()
7887   );
7888   pr ")"
7889
7890 (* Generate the OCaml bindings interface. *)
7891 and generate_ocaml_mli () =
7892   generate_header OCamlStyle LGPLv2plus;
7893
7894   pr "\
7895 (** For API documentation you should refer to the C API
7896     in the guestfs(3) manual page.  The OCaml API uses almost
7897     exactly the same calls. *)
7898
7899 type t
7900 (** A [guestfs_h] handle. *)
7901
7902 exception Error of string
7903 (** This exception is raised when there is an error. *)
7904
7905 exception Handle_closed of string
7906 (** This exception is raised if you use a {!Guestfs.t} handle
7907     after calling {!close} on it.  The string is the name of
7908     the function. *)
7909
7910 val create : unit -> t
7911 (** Create a {!Guestfs.t} handle. *)
7912
7913 val close : t -> unit
7914 (** Close the {!Guestfs.t} handle and free up all resources used
7915     by it immediately.
7916
7917     Handles are closed by the garbage collector when they become
7918     unreferenced, but callers can call this in order to provide
7919     predictable cleanup. *)
7920
7921 ";
7922   generate_ocaml_structure_decls ();
7923
7924   (* The actions. *)
7925   List.iter (
7926     fun (name, style, _, _, _, shortdesc, _) ->
7927       generate_ocaml_prototype name style;
7928       pr "(** %s *)\n" shortdesc;
7929       pr "\n"
7930   ) all_functions_sorted
7931
7932 (* Generate the OCaml bindings implementation. *)
7933 and generate_ocaml_ml () =
7934   generate_header OCamlStyle LGPLv2plus;
7935
7936   pr "\
7937 type t
7938
7939 exception Error of string
7940 exception Handle_closed of string
7941
7942 external create : unit -> t = \"ocaml_guestfs_create\"
7943 external close : t -> unit = \"ocaml_guestfs_close\"
7944
7945 (* Give the exceptions names, so they can be raised from the C code. *)
7946 let () =
7947   Callback.register_exception \"ocaml_guestfs_error\" (Error \"\");
7948   Callback.register_exception \"ocaml_guestfs_closed\" (Handle_closed \"\")
7949
7950 ";
7951
7952   generate_ocaml_structure_decls ();
7953
7954   (* The actions. *)
7955   List.iter (
7956     fun (name, style, _, _, _, shortdesc, _) ->
7957       generate_ocaml_prototype ~is_external:true name style;
7958   ) all_functions_sorted
7959
7960 (* Generate the OCaml bindings C implementation. *)
7961 and generate_ocaml_c () =
7962   generate_header CStyle LGPLv2plus;
7963
7964   pr "\
7965 #include <stdio.h>
7966 #include <stdlib.h>
7967 #include <string.h>
7968
7969 #include <caml/config.h>
7970 #include <caml/alloc.h>
7971 #include <caml/callback.h>
7972 #include <caml/fail.h>
7973 #include <caml/memory.h>
7974 #include <caml/mlvalues.h>
7975 #include <caml/signals.h>
7976
7977 #include <guestfs.h>
7978
7979 #include \"guestfs_c.h\"
7980
7981 /* Copy a hashtable of string pairs into an assoc-list.  We return
7982  * the list in reverse order, but hashtables aren't supposed to be
7983  * ordered anyway.
7984  */
7985 static CAMLprim value
7986 copy_table (char * const * argv)
7987 {
7988   CAMLparam0 ();
7989   CAMLlocal5 (rv, pairv, kv, vv, cons);
7990   int i;
7991
7992   rv = Val_int (0);
7993   for (i = 0; argv[i] != NULL; i += 2) {
7994     kv = caml_copy_string (argv[i]);
7995     vv = caml_copy_string (argv[i+1]);
7996     pairv = caml_alloc (2, 0);
7997     Store_field (pairv, 0, kv);
7998     Store_field (pairv, 1, vv);
7999     cons = caml_alloc (2, 0);
8000     Store_field (cons, 1, rv);
8001     rv = cons;
8002     Store_field (cons, 0, pairv);
8003   }
8004
8005   CAMLreturn (rv);
8006 }
8007
8008 ";
8009
8010   (* Struct copy functions. *)
8011
8012   let emit_ocaml_copy_list_function typ =
8013     pr "static CAMLprim value\n";
8014     pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
8015     pr "{\n";
8016     pr "  CAMLparam0 ();\n";
8017     pr "  CAMLlocal2 (rv, v);\n";
8018     pr "  unsigned int i;\n";
8019     pr "\n";
8020     pr "  if (%ss->len == 0)\n" typ;
8021     pr "    CAMLreturn (Atom (0));\n";
8022     pr "  else {\n";
8023     pr "    rv = caml_alloc (%ss->len, 0);\n" typ;
8024     pr "    for (i = 0; i < %ss->len; ++i) {\n" typ;
8025     pr "      v = copy_%s (&%ss->val[i]);\n" typ typ;
8026     pr "      caml_modify (&Field (rv, i), v);\n";
8027     pr "    }\n";
8028     pr "    CAMLreturn (rv);\n";
8029     pr "  }\n";
8030     pr "}\n";
8031     pr "\n";
8032   in
8033
8034   List.iter (
8035     fun (typ, cols) ->
8036       let has_optpercent_col =
8037         List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
8038
8039       pr "static CAMLprim value\n";
8040       pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
8041       pr "{\n";
8042       pr "  CAMLparam0 ();\n";
8043       if has_optpercent_col then
8044         pr "  CAMLlocal3 (rv, v, v2);\n"
8045       else
8046         pr "  CAMLlocal2 (rv, v);\n";
8047       pr "\n";
8048       pr "  rv = caml_alloc (%d, 0);\n" (List.length cols);
8049       iteri (
8050         fun i col ->
8051           (match col with
8052            | name, FString ->
8053                pr "  v = caml_copy_string (%s->%s);\n" typ name
8054            | name, FBuffer ->
8055                pr "  v = caml_alloc_string (%s->%s_len);\n" typ name;
8056                pr "  memcpy (String_val (v), %s->%s, %s->%s_len);\n"
8057                  typ name typ name
8058            | name, FUUID ->
8059                pr "  v = caml_alloc_string (32);\n";
8060                pr "  memcpy (String_val (v), %s->%s, 32);\n" typ name
8061            | name, (FBytes|FInt64|FUInt64) ->
8062                pr "  v = caml_copy_int64 (%s->%s);\n" typ name
8063            | name, (FInt32|FUInt32) ->
8064                pr "  v = caml_copy_int32 (%s->%s);\n" typ name
8065            | name, FOptPercent ->
8066                pr "  if (%s->%s >= 0) { /* Some %s */\n" typ name name;
8067                pr "    v2 = caml_copy_double (%s->%s);\n" typ name;
8068                pr "    v = caml_alloc (1, 0);\n";
8069                pr "    Store_field (v, 0, v2);\n";
8070                pr "  } else /* None */\n";
8071                pr "    v = Val_int (0);\n";
8072            | name, FChar ->
8073                pr "  v = Val_int (%s->%s);\n" typ name
8074           );
8075           pr "  Store_field (rv, %d, v);\n" i
8076       ) cols;
8077       pr "  CAMLreturn (rv);\n";
8078       pr "}\n";
8079       pr "\n";
8080   ) structs;
8081
8082   (* Emit a copy_TYPE_list function definition only if that function is used. *)
8083   List.iter (
8084     function
8085     | typ, (RStructListOnly | RStructAndList) ->
8086         (* generate the function for typ *)
8087         emit_ocaml_copy_list_function typ
8088     | typ, _ -> () (* empty *)
8089   ) (rstructs_used_by all_functions);
8090
8091   (* The wrappers. *)
8092   List.iter (
8093     fun (name, style, _, _, _, _, _) ->
8094       pr "/* Automatically generated wrapper for function\n";
8095       pr " * ";
8096       generate_ocaml_prototype name style;
8097       pr " */\n";
8098       pr "\n";
8099
8100       let params =
8101         "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
8102
8103       let needs_extra_vs =
8104         match fst style with RConstOptString _ -> true | _ -> false in
8105
8106       pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8107       pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
8108       List.iter (pr ", value %s") (List.tl params); pr ");\n";
8109       pr "\n";
8110
8111       pr "CAMLprim value\n";
8112       pr "ocaml_guestfs_%s (value %s" name (List.hd params);
8113       List.iter (pr ", value %s") (List.tl params);
8114       pr ")\n";
8115       pr "{\n";
8116
8117       (match params with
8118        | [p1; p2; p3; p4; p5] ->
8119            pr "  CAMLparam5 (%s);\n" (String.concat ", " params)
8120        | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
8121            pr "  CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
8122            pr "  CAMLxparam%d (%s);\n"
8123              (List.length rest) (String.concat ", " rest)
8124        | ps ->
8125            pr "  CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
8126       );
8127       if not needs_extra_vs then
8128         pr "  CAMLlocal1 (rv);\n"
8129       else
8130         pr "  CAMLlocal3 (rv, v, v2);\n";
8131       pr "\n";
8132
8133       pr "  guestfs_h *g = Guestfs_val (gv);\n";
8134       pr "  if (g == NULL)\n";
8135       pr "    ocaml_guestfs_raise_closed (\"%s\");\n" name;
8136       pr "\n";
8137
8138       List.iter (
8139         function
8140         | Pathname n
8141         | Device n | Dev_or_Path n
8142         | String n
8143         | FileIn n
8144         | FileOut n ->
8145             pr "  const char *%s = String_val (%sv);\n" n n
8146         | OptString n ->
8147             pr "  const char *%s =\n" n;
8148             pr "    %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
8149               n n
8150         | StringList n | DeviceList n ->
8151             pr "  char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
8152         | Bool n ->
8153             pr "  int %s = Bool_val (%sv);\n" n n
8154         | Int n ->
8155             pr "  int %s = Int_val (%sv);\n" n n
8156         | Int64 n ->
8157             pr "  int64_t %s = Int64_val (%sv);\n" n n
8158       ) (snd style);
8159       let error_code =
8160         match fst style with
8161         | RErr -> pr "  int r;\n"; "-1"
8162         | RInt _ -> pr "  int r;\n"; "-1"
8163         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8164         | RBool _ -> pr "  int r;\n"; "-1"
8165         | RConstString _ | RConstOptString _ ->
8166             pr "  const char *r;\n"; "NULL"
8167         | RString _ -> pr "  char *r;\n"; "NULL"
8168         | RStringList _ ->
8169             pr "  int i;\n";
8170             pr "  char **r;\n";
8171             "NULL"
8172         | RStruct (_, typ) ->
8173             pr "  struct guestfs_%s *r;\n" typ; "NULL"
8174         | RStructList (_, typ) ->
8175             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8176         | RHashtable _ ->
8177             pr "  int i;\n";
8178             pr "  char **r;\n";
8179             "NULL"
8180         | RBufferOut _ ->
8181             pr "  char *r;\n";
8182             pr "  size_t size;\n";
8183             "NULL" in
8184       pr "\n";
8185
8186       pr "  caml_enter_blocking_section ();\n";
8187       pr "  r = guestfs_%s " name;
8188       generate_c_call_args ~handle:"g" style;
8189       pr ";\n";
8190       pr "  caml_leave_blocking_section ();\n";
8191
8192       List.iter (
8193         function
8194         | StringList n | DeviceList n ->
8195             pr "  ocaml_guestfs_free_strings (%s);\n" n;
8196         | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8197         | Bool _ | Int _ | Int64 _
8198         | FileIn _ | FileOut _ -> ()
8199       ) (snd style);
8200
8201       pr "  if (r == %s)\n" error_code;
8202       pr "    ocaml_guestfs_raise_error (g, \"%s\");\n" name;
8203       pr "\n";
8204
8205       (match fst style with
8206        | RErr -> pr "  rv = Val_unit;\n"
8207        | RInt _ -> pr "  rv = Val_int (r);\n"
8208        | RInt64 _ ->
8209            pr "  rv = caml_copy_int64 (r);\n"
8210        | RBool _ -> pr "  rv = Val_bool (r);\n"
8211        | RConstString _ ->
8212            pr "  rv = caml_copy_string (r);\n"
8213        | RConstOptString _ ->
8214            pr "  if (r) { /* Some string */\n";
8215            pr "    v = caml_alloc (1, 0);\n";
8216            pr "    v2 = caml_copy_string (r);\n";
8217            pr "    Store_field (v, 0, v2);\n";
8218            pr "  } else /* None */\n";
8219            pr "    v = Val_int (0);\n";
8220        | RString _ ->
8221            pr "  rv = caml_copy_string (r);\n";
8222            pr "  free (r);\n"
8223        | RStringList _ ->
8224            pr "  rv = caml_copy_string_array ((const char **) r);\n";
8225            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8226            pr "  free (r);\n"
8227        | RStruct (_, typ) ->
8228            pr "  rv = copy_%s (r);\n" typ;
8229            pr "  guestfs_free_%s (r);\n" typ;
8230        | RStructList (_, typ) ->
8231            pr "  rv = copy_%s_list (r);\n" typ;
8232            pr "  guestfs_free_%s_list (r);\n" typ;
8233        | RHashtable _ ->
8234            pr "  rv = copy_table (r);\n";
8235            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8236            pr "  free (r);\n";
8237        | RBufferOut _ ->
8238            pr "  rv = caml_alloc_string (size);\n";
8239            pr "  memcpy (String_val (rv), r, size);\n";
8240       );
8241
8242       pr "  CAMLreturn (rv);\n";
8243       pr "}\n";
8244       pr "\n";
8245
8246       if List.length params > 5 then (
8247         pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8248         pr "CAMLprim value ";
8249         pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
8250         pr "CAMLprim value\n";
8251         pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
8252         pr "{\n";
8253         pr "  return ocaml_guestfs_%s (argv[0]" name;
8254         iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
8255         pr ");\n";
8256         pr "}\n";
8257         pr "\n"
8258       )
8259   ) all_functions_sorted
8260
8261 and generate_ocaml_structure_decls () =
8262   List.iter (
8263     fun (typ, cols) ->
8264       pr "type %s = {\n" typ;
8265       List.iter (
8266         function
8267         | name, FString -> pr "  %s : string;\n" name
8268         | name, FBuffer -> pr "  %s : string;\n" name
8269         | name, FUUID -> pr "  %s : string;\n" name
8270         | name, (FBytes|FInt64|FUInt64) -> pr "  %s : int64;\n" name
8271         | name, (FInt32|FUInt32) -> pr "  %s : int32;\n" name
8272         | name, FChar -> pr "  %s : char;\n" name
8273         | name, FOptPercent -> pr "  %s : float option;\n" name
8274       ) cols;
8275       pr "}\n";
8276       pr "\n"
8277   ) structs
8278
8279 and generate_ocaml_prototype ?(is_external = false) name style =
8280   if is_external then pr "external " else pr "val ";
8281   pr "%s : t -> " name;
8282   List.iter (
8283     function
8284     | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "string -> "
8285     | OptString _ -> pr "string option -> "
8286     | StringList _ | DeviceList _ -> pr "string array -> "
8287     | Bool _ -> pr "bool -> "
8288     | Int _ -> pr "int -> "
8289     | Int64 _ -> pr "int64 -> "
8290   ) (snd style);
8291   (match fst style with
8292    | RErr -> pr "unit" (* all errors are turned into exceptions *)
8293    | RInt _ -> pr "int"
8294    | RInt64 _ -> pr "int64"
8295    | RBool _ -> pr "bool"
8296    | RConstString _ -> pr "string"
8297    | RConstOptString _ -> pr "string option"
8298    | RString _ | RBufferOut _ -> pr "string"
8299    | RStringList _ -> pr "string array"
8300    | RStruct (_, typ) -> pr "%s" typ
8301    | RStructList (_, typ) -> pr "%s array" typ
8302    | RHashtable _ -> pr "(string * string) list"
8303   );
8304   if is_external then (
8305     pr " = ";
8306     if List.length (snd style) + 1 > 5 then
8307       pr "\"ocaml_guestfs_%s_byte\" " name;
8308     pr "\"ocaml_guestfs_%s\"" name
8309   );
8310   pr "\n"
8311
8312 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
8313 and generate_perl_xs () =
8314   generate_header CStyle LGPLv2plus;
8315
8316   pr "\
8317 #include \"EXTERN.h\"
8318 #include \"perl.h\"
8319 #include \"XSUB.h\"
8320
8321 #include <guestfs.h>
8322
8323 #ifndef PRId64
8324 #define PRId64 \"lld\"
8325 #endif
8326
8327 static SV *
8328 my_newSVll(long long val) {
8329 #ifdef USE_64_BIT_ALL
8330   return newSViv(val);
8331 #else
8332   char buf[100];
8333   int len;
8334   len = snprintf(buf, 100, \"%%\" PRId64, val);
8335   return newSVpv(buf, len);
8336 #endif
8337 }
8338
8339 #ifndef PRIu64
8340 #define PRIu64 \"llu\"
8341 #endif
8342
8343 static SV *
8344 my_newSVull(unsigned long long val) {
8345 #ifdef USE_64_BIT_ALL
8346   return newSVuv(val);
8347 #else
8348   char buf[100];
8349   int len;
8350   len = snprintf(buf, 100, \"%%\" PRIu64, val);
8351   return newSVpv(buf, len);
8352 #endif
8353 }
8354
8355 /* http://www.perlmonks.org/?node_id=680842 */
8356 static char **
8357 XS_unpack_charPtrPtr (SV *arg) {
8358   char **ret;
8359   AV *av;
8360   I32 i;
8361
8362   if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
8363     croak (\"array reference expected\");
8364
8365   av = (AV *)SvRV (arg);
8366   ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
8367   if (!ret)
8368     croak (\"malloc failed\");
8369
8370   for (i = 0; i <= av_len (av); i++) {
8371     SV **elem = av_fetch (av, i, 0);
8372
8373     if (!elem || !*elem)
8374       croak (\"missing element in list\");
8375
8376     ret[i] = SvPV_nolen (*elem);
8377   }
8378
8379   ret[i] = NULL;
8380
8381   return ret;
8382 }
8383
8384 MODULE = Sys::Guestfs  PACKAGE = Sys::Guestfs
8385
8386 PROTOTYPES: ENABLE
8387
8388 guestfs_h *
8389 _create ()
8390    CODE:
8391       RETVAL = guestfs_create ();
8392       if (!RETVAL)
8393         croak (\"could not create guestfs handle\");
8394       guestfs_set_error_handler (RETVAL, NULL, NULL);
8395  OUTPUT:
8396       RETVAL
8397
8398 void
8399 DESTROY (g)
8400       guestfs_h *g;
8401  PPCODE:
8402       guestfs_close (g);
8403
8404 ";
8405
8406   List.iter (
8407     fun (name, style, _, _, _, _, _) ->
8408       (match fst style with
8409        | RErr -> pr "void\n"
8410        | RInt _ -> pr "SV *\n"
8411        | RInt64 _ -> pr "SV *\n"
8412        | RBool _ -> pr "SV *\n"
8413        | RConstString _ -> pr "SV *\n"
8414        | RConstOptString _ -> pr "SV *\n"
8415        | RString _ -> pr "SV *\n"
8416        | RBufferOut _ -> pr "SV *\n"
8417        | RStringList _
8418        | RStruct _ | RStructList _
8419        | RHashtable _ ->
8420            pr "void\n" (* all lists returned implictly on the stack *)
8421       );
8422       (* Call and arguments. *)
8423       pr "%s " name;
8424       generate_c_call_args ~handle:"g" ~decl:true style;
8425       pr "\n";
8426       pr "      guestfs_h *g;\n";
8427       iteri (
8428         fun i ->
8429           function
8430           | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8431               pr "      char *%s;\n" n
8432           | OptString n ->
8433               (* http://www.perlmonks.org/?node_id=554277
8434                * Note that the implicit handle argument means we have
8435                * to add 1 to the ST(x) operator.
8436                *)
8437               pr "      char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
8438           | StringList n | DeviceList n -> pr "      char **%s;\n" n
8439           | Bool n -> pr "      int %s;\n" n
8440           | Int n -> pr "      int %s;\n" n
8441           | Int64 n -> pr "      int64_t %s;\n" n
8442       ) (snd style);
8443
8444       let do_cleanups () =
8445         List.iter (
8446           function
8447           | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8448           | Bool _ | Int _ | Int64 _
8449           | FileIn _ | FileOut _ -> ()
8450           | StringList n | DeviceList n -> pr "      free (%s);\n" n
8451         ) (snd style)
8452       in
8453
8454       (* Code. *)
8455       (match fst style with
8456        | RErr ->
8457            pr "PREINIT:\n";
8458            pr "      int r;\n";
8459            pr " PPCODE:\n";
8460            pr "      r = guestfs_%s " name;
8461            generate_c_call_args ~handle:"g" style;
8462            pr ";\n";
8463            do_cleanups ();
8464            pr "      if (r == -1)\n";
8465            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8466        | RInt n
8467        | RBool n ->
8468            pr "PREINIT:\n";
8469            pr "      int %s;\n" n;
8470            pr "   CODE:\n";
8471            pr "      %s = guestfs_%s " n name;
8472            generate_c_call_args ~handle:"g" style;
8473            pr ";\n";
8474            do_cleanups ();
8475            pr "      if (%s == -1)\n" n;
8476            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8477            pr "      RETVAL = newSViv (%s);\n" n;
8478            pr " OUTPUT:\n";
8479            pr "      RETVAL\n"
8480        | RInt64 n ->
8481            pr "PREINIT:\n";
8482            pr "      int64_t %s;\n" n;
8483            pr "   CODE:\n";
8484            pr "      %s = guestfs_%s " n name;
8485            generate_c_call_args ~handle:"g" style;
8486            pr ";\n";
8487            do_cleanups ();
8488            pr "      if (%s == -1)\n" n;
8489            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8490            pr "      RETVAL = my_newSVll (%s);\n" n;
8491            pr " OUTPUT:\n";
8492            pr "      RETVAL\n"
8493        | RConstString n ->
8494            pr "PREINIT:\n";
8495            pr "      const char *%s;\n" n;
8496            pr "   CODE:\n";
8497            pr "      %s = guestfs_%s " n name;
8498            generate_c_call_args ~handle:"g" style;
8499            pr ";\n";
8500            do_cleanups ();
8501            pr "      if (%s == NULL)\n" n;
8502            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8503            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8504            pr " OUTPUT:\n";
8505            pr "      RETVAL\n"
8506        | RConstOptString n ->
8507            pr "PREINIT:\n";
8508            pr "      const char *%s;\n" n;
8509            pr "   CODE:\n";
8510            pr "      %s = guestfs_%s " n name;
8511            generate_c_call_args ~handle:"g" style;
8512            pr ";\n";
8513            do_cleanups ();
8514            pr "      if (%s == NULL)\n" n;
8515            pr "        RETVAL = &PL_sv_undef;\n";
8516            pr "      else\n";
8517            pr "        RETVAL = newSVpv (%s, 0);\n" n;
8518            pr " OUTPUT:\n";
8519            pr "      RETVAL\n"
8520        | RString n ->
8521            pr "PREINIT:\n";
8522            pr "      char *%s;\n" n;
8523            pr "   CODE:\n";
8524            pr "      %s = guestfs_%s " n name;
8525            generate_c_call_args ~handle:"g" style;
8526            pr ";\n";
8527            do_cleanups ();
8528            pr "      if (%s == NULL)\n" n;
8529            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8530            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8531            pr "      free (%s);\n" n;
8532            pr " OUTPUT:\n";
8533            pr "      RETVAL\n"
8534        | RStringList n | RHashtable n ->
8535            pr "PREINIT:\n";
8536            pr "      char **%s;\n" n;
8537            pr "      int i, n;\n";
8538            pr " PPCODE:\n";
8539            pr "      %s = guestfs_%s " n name;
8540            generate_c_call_args ~handle:"g" style;
8541            pr ";\n";
8542            do_cleanups ();
8543            pr "      if (%s == NULL)\n" n;
8544            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8545            pr "      for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
8546            pr "      EXTEND (SP, n);\n";
8547            pr "      for (i = 0; i < n; ++i) {\n";
8548            pr "        PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
8549            pr "        free (%s[i]);\n" n;
8550            pr "      }\n";
8551            pr "      free (%s);\n" n;
8552        | RStruct (n, typ) ->
8553            let cols = cols_of_struct typ in
8554            generate_perl_struct_code typ cols name style n do_cleanups
8555        | RStructList (n, typ) ->
8556            let cols = cols_of_struct typ in
8557            generate_perl_struct_list_code typ cols name style n do_cleanups
8558        | RBufferOut n ->
8559            pr "PREINIT:\n";
8560            pr "      char *%s;\n" n;
8561            pr "      size_t size;\n";
8562            pr "   CODE:\n";
8563            pr "      %s = guestfs_%s " n name;
8564            generate_c_call_args ~handle:"g" style;
8565            pr ";\n";
8566            do_cleanups ();
8567            pr "      if (%s == NULL)\n" n;
8568            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8569            pr "      RETVAL = newSVpvn (%s, size);\n" n;
8570            pr "      free (%s);\n" n;
8571            pr " OUTPUT:\n";
8572            pr "      RETVAL\n"
8573       );
8574
8575       pr "\n"
8576   ) all_functions
8577
8578 and generate_perl_struct_list_code typ cols name style n do_cleanups =
8579   pr "PREINIT:\n";
8580   pr "      struct guestfs_%s_list *%s;\n" typ n;
8581   pr "      int i;\n";
8582   pr "      HV *hv;\n";
8583   pr " PPCODE:\n";
8584   pr "      %s = guestfs_%s " n name;
8585   generate_c_call_args ~handle:"g" style;
8586   pr ";\n";
8587   do_cleanups ();
8588   pr "      if (%s == NULL)\n" n;
8589   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8590   pr "      EXTEND (SP, %s->len);\n" n;
8591   pr "      for (i = 0; i < %s->len; ++i) {\n" n;
8592   pr "        hv = newHV ();\n";
8593   List.iter (
8594     function
8595     | name, FString ->
8596         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
8597           name (String.length name) n name
8598     | name, FUUID ->
8599         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
8600           name (String.length name) n name
8601     | name, FBuffer ->
8602         pr "        (void) hv_store (hv, \"%s\", %d, newSVpvn (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
8603           name (String.length name) n name n name
8604     | name, (FBytes|FUInt64) ->
8605         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
8606           name (String.length name) n name
8607     | name, FInt64 ->
8608         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
8609           name (String.length name) n name
8610     | name, (FInt32|FUInt32) ->
8611         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8612           name (String.length name) n name
8613     | name, FChar ->
8614         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
8615           name (String.length name) n name
8616     | name, FOptPercent ->
8617         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8618           name (String.length name) n name
8619   ) cols;
8620   pr "        PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
8621   pr "      }\n";
8622   pr "      guestfs_free_%s_list (%s);\n" typ n
8623
8624 and generate_perl_struct_code typ cols name style n do_cleanups =
8625   pr "PREINIT:\n";
8626   pr "      struct guestfs_%s *%s;\n" typ n;
8627   pr " PPCODE:\n";
8628   pr "      %s = guestfs_%s " n name;
8629   generate_c_call_args ~handle:"g" style;
8630   pr ";\n";
8631   do_cleanups ();
8632   pr "      if (%s == NULL)\n" n;
8633   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8634   pr "      EXTEND (SP, 2 * %d);\n" (List.length cols);
8635   List.iter (
8636     fun ((name, _) as col) ->
8637       pr "      PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
8638
8639       match col with
8640       | name, FString ->
8641           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
8642             n name
8643       | name, FBuffer ->
8644           pr "      PUSHs (sv_2mortal (newSVpvn (%s->%s, %s->%s_len)));\n"
8645             n name n name
8646       | name, FUUID ->
8647           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
8648             n name
8649       | name, (FBytes|FUInt64) ->
8650           pr "      PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
8651             n name
8652       | name, FInt64 ->
8653           pr "      PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
8654             n name
8655       | name, (FInt32|FUInt32) ->
8656           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8657             n name
8658       | name, FChar ->
8659           pr "      PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
8660             n name
8661       | name, FOptPercent ->
8662           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8663             n name
8664   ) cols;
8665   pr "      free (%s);\n" n
8666
8667 (* Generate Sys/Guestfs.pm. *)
8668 and generate_perl_pm () =
8669   generate_header HashStyle LGPLv2plus;
8670
8671   pr "\
8672 =pod
8673
8674 =head1 NAME
8675
8676 Sys::Guestfs - Perl bindings for libguestfs
8677
8678 =head1 SYNOPSIS
8679
8680  use Sys::Guestfs;
8681
8682  my $h = Sys::Guestfs->new ();
8683  $h->add_drive ('guest.img');
8684  $h->launch ();
8685  $h->mount ('/dev/sda1', '/');
8686  $h->touch ('/hello');
8687  $h->sync ();
8688
8689 =head1 DESCRIPTION
8690
8691 The C<Sys::Guestfs> module provides a Perl XS binding to the
8692 libguestfs API for examining and modifying virtual machine
8693 disk images.
8694
8695 Amongst the things this is good for: making batch configuration
8696 changes to guests, getting disk used/free statistics (see also:
8697 virt-df), migrating between virtualization systems (see also:
8698 virt-p2v), performing partial backups, performing partial guest
8699 clones, cloning guests and changing registry/UUID/hostname info, and
8700 much else besides.
8701
8702 Libguestfs uses Linux kernel and qemu code, and can access any type of
8703 guest filesystem that Linux and qemu can, including but not limited
8704 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8705 schemes, qcow, qcow2, vmdk.
8706
8707 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8708 LVs, what filesystem is in each LV, etc.).  It can also run commands
8709 in the context of the guest.  Also you can access filesystems over
8710 FUSE.
8711
8712 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
8713 functions for using libguestfs from Perl, including integration
8714 with libvirt.
8715
8716 =head1 ERRORS
8717
8718 All errors turn into calls to C<croak> (see L<Carp(3)>).
8719
8720 =head1 METHODS
8721
8722 =over 4
8723
8724 =cut
8725
8726 package Sys::Guestfs;
8727
8728 use strict;
8729 use warnings;
8730
8731 require XSLoader;
8732 XSLoader::load ('Sys::Guestfs');
8733
8734 =item $h = Sys::Guestfs->new ();
8735
8736 Create a new guestfs handle.
8737
8738 =cut
8739
8740 sub new {
8741   my $proto = shift;
8742   my $class = ref ($proto) || $proto;
8743
8744   my $self = Sys::Guestfs::_create ();
8745   bless $self, $class;
8746   return $self;
8747 }
8748
8749 ";
8750
8751   (* Actions.  We only need to print documentation for these as
8752    * they are pulled in from the XS code automatically.
8753    *)
8754   List.iter (
8755     fun (name, style, _, flags, _, _, longdesc) ->
8756       if not (List.mem NotInDocs flags) then (
8757         let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
8758         pr "=item ";
8759         generate_perl_prototype name style;
8760         pr "\n\n";
8761         pr "%s\n\n" longdesc;
8762         if List.mem ProtocolLimitWarning flags then
8763           pr "%s\n\n" protocol_limit_warning;
8764         if List.mem DangerWillRobinson flags then
8765           pr "%s\n\n" danger_will_robinson;
8766         match deprecation_notice flags with
8767         | None -> ()
8768         | Some txt -> pr "%s\n\n" txt
8769       )
8770   ) all_functions_sorted;
8771
8772   (* End of file. *)
8773   pr "\
8774 =cut
8775
8776 1;
8777
8778 =back
8779
8780 =head1 COPYRIGHT
8781
8782 Copyright (C) %s Red Hat Inc.
8783
8784 =head1 LICENSE
8785
8786 Please see the file COPYING.LIB for the full license.
8787
8788 =head1 SEE ALSO
8789
8790 L<guestfs(3)>,
8791 L<guestfish(1)>,
8792 L<http://libguestfs.org>,
8793 L<Sys::Guestfs::Lib(3)>.
8794
8795 =cut
8796 " copyright_years
8797
8798 and generate_perl_prototype name style =
8799   (match fst style with
8800    | RErr -> ()
8801    | RBool n
8802    | RInt n
8803    | RInt64 n
8804    | RConstString n
8805    | RConstOptString n
8806    | RString n
8807    | RBufferOut n -> pr "$%s = " n
8808    | RStruct (n,_)
8809    | RHashtable n -> pr "%%%s = " n
8810    | RStringList n
8811    | RStructList (n,_) -> pr "@%s = " n
8812   );
8813   pr "$h->%s (" name;
8814   let comma = ref false in
8815   List.iter (
8816     fun arg ->
8817       if !comma then pr ", ";
8818       comma := true;
8819       match arg with
8820       | Pathname n | Device n | Dev_or_Path n | String n
8821       | OptString n | Bool n | Int n | Int64 n | FileIn n | FileOut n ->
8822           pr "$%s" n
8823       | StringList n | DeviceList n ->
8824           pr "\\@%s" n
8825   ) (snd style);
8826   pr ");"
8827
8828 (* Generate Python C module. *)
8829 and generate_python_c () =
8830   generate_header CStyle LGPLv2plus;
8831
8832   pr "\
8833 #include <Python.h>
8834
8835 #include <stdio.h>
8836 #include <stdlib.h>
8837 #include <assert.h>
8838
8839 #include \"guestfs.h\"
8840
8841 typedef struct {
8842   PyObject_HEAD
8843   guestfs_h *g;
8844 } Pyguestfs_Object;
8845
8846 static guestfs_h *
8847 get_handle (PyObject *obj)
8848 {
8849   assert (obj);
8850   assert (obj != Py_None);
8851   return ((Pyguestfs_Object *) obj)->g;
8852 }
8853
8854 static PyObject *
8855 put_handle (guestfs_h *g)
8856 {
8857   assert (g);
8858   return
8859     PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
8860 }
8861
8862 /* This list should be freed (but not the strings) after use. */
8863 static char **
8864 get_string_list (PyObject *obj)
8865 {
8866   int i, len;
8867   char **r;
8868
8869   assert (obj);
8870
8871   if (!PyList_Check (obj)) {
8872     PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
8873     return NULL;
8874   }
8875
8876   len = PyList_Size (obj);
8877   r = malloc (sizeof (char *) * (len+1));
8878   if (r == NULL) {
8879     PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
8880     return NULL;
8881   }
8882
8883   for (i = 0; i < len; ++i)
8884     r[i] = PyString_AsString (PyList_GetItem (obj, i));
8885   r[len] = NULL;
8886
8887   return r;
8888 }
8889
8890 static PyObject *
8891 put_string_list (char * const * const argv)
8892 {
8893   PyObject *list;
8894   int argc, i;
8895
8896   for (argc = 0; argv[argc] != NULL; ++argc)
8897     ;
8898
8899   list = PyList_New (argc);
8900   for (i = 0; i < argc; ++i)
8901     PyList_SetItem (list, i, PyString_FromString (argv[i]));
8902
8903   return list;
8904 }
8905
8906 static PyObject *
8907 put_table (char * const * const argv)
8908 {
8909   PyObject *list, *item;
8910   int argc, i;
8911
8912   for (argc = 0; argv[argc] != NULL; ++argc)
8913     ;
8914
8915   list = PyList_New (argc >> 1);
8916   for (i = 0; i < argc; i += 2) {
8917     item = PyTuple_New (2);
8918     PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
8919     PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
8920     PyList_SetItem (list, i >> 1, item);
8921   }
8922
8923   return list;
8924 }
8925
8926 static void
8927 free_strings (char **argv)
8928 {
8929   int argc;
8930
8931   for (argc = 0; argv[argc] != NULL; ++argc)
8932     free (argv[argc]);
8933   free (argv);
8934 }
8935
8936 static PyObject *
8937 py_guestfs_create (PyObject *self, PyObject *args)
8938 {
8939   guestfs_h *g;
8940
8941   g = guestfs_create ();
8942   if (g == NULL) {
8943     PyErr_SetString (PyExc_RuntimeError,
8944                      \"guestfs.create: failed to allocate handle\");
8945     return NULL;
8946   }
8947   guestfs_set_error_handler (g, NULL, NULL);
8948   return put_handle (g);
8949 }
8950
8951 static PyObject *
8952 py_guestfs_close (PyObject *self, PyObject *args)
8953 {
8954   PyObject *py_g;
8955   guestfs_h *g;
8956
8957   if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
8958     return NULL;
8959   g = get_handle (py_g);
8960
8961   guestfs_close (g);
8962
8963   Py_INCREF (Py_None);
8964   return Py_None;
8965 }
8966
8967 ";
8968
8969   let emit_put_list_function typ =
8970     pr "static PyObject *\n";
8971     pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
8972     pr "{\n";
8973     pr "  PyObject *list;\n";
8974     pr "  int i;\n";
8975     pr "\n";
8976     pr "  list = PyList_New (%ss->len);\n" typ;
8977     pr "  for (i = 0; i < %ss->len; ++i)\n" typ;
8978     pr "    PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
8979     pr "  return list;\n";
8980     pr "};\n";
8981     pr "\n"
8982   in
8983
8984   (* Structures, turned into Python dictionaries. *)
8985   List.iter (
8986     fun (typ, cols) ->
8987       pr "static PyObject *\n";
8988       pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
8989       pr "{\n";
8990       pr "  PyObject *dict;\n";
8991       pr "\n";
8992       pr "  dict = PyDict_New ();\n";
8993       List.iter (
8994         function
8995         | name, FString ->
8996             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8997             pr "                        PyString_FromString (%s->%s));\n"
8998               typ name
8999         | name, FBuffer ->
9000             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9001             pr "                        PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
9002               typ name typ name
9003         | name, FUUID ->
9004             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9005             pr "                        PyString_FromStringAndSize (%s->%s, 32));\n"
9006               typ name
9007         | name, (FBytes|FUInt64) ->
9008             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9009             pr "                        PyLong_FromUnsignedLongLong (%s->%s));\n"
9010               typ name
9011         | name, FInt64 ->
9012             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9013             pr "                        PyLong_FromLongLong (%s->%s));\n"
9014               typ name
9015         | name, FUInt32 ->
9016             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9017             pr "                        PyLong_FromUnsignedLong (%s->%s));\n"
9018               typ name
9019         | name, FInt32 ->
9020             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9021             pr "                        PyLong_FromLong (%s->%s));\n"
9022               typ name
9023         | name, FOptPercent ->
9024             pr "  if (%s->%s >= 0)\n" typ name;
9025             pr "    PyDict_SetItemString (dict, \"%s\",\n" name;
9026             pr "                          PyFloat_FromDouble ((double) %s->%s));\n"
9027               typ name;
9028             pr "  else {\n";
9029             pr "    Py_INCREF (Py_None);\n";
9030             pr "    PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
9031             pr "  }\n"
9032         | name, FChar ->
9033             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9034             pr "                        PyString_FromStringAndSize (&dirent->%s, 1));\n" name
9035       ) cols;
9036       pr "  return dict;\n";
9037       pr "};\n";
9038       pr "\n";
9039
9040   ) structs;
9041
9042   (* Emit a put_TYPE_list function definition only if that function is used. *)
9043   List.iter (
9044     function
9045     | typ, (RStructListOnly | RStructAndList) ->
9046         (* generate the function for typ *)
9047         emit_put_list_function typ
9048     | typ, _ -> () (* empty *)
9049   ) (rstructs_used_by all_functions);
9050
9051   (* Python wrapper functions. *)
9052   List.iter (
9053     fun (name, style, _, _, _, _, _) ->
9054       pr "static PyObject *\n";
9055       pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
9056       pr "{\n";
9057
9058       pr "  PyObject *py_g;\n";
9059       pr "  guestfs_h *g;\n";
9060       pr "  PyObject *py_r;\n";
9061
9062       let error_code =
9063         match fst style with
9064         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
9065         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
9066         | RConstString _ | RConstOptString _ ->
9067             pr "  const char *r;\n"; "NULL"
9068         | RString _ -> pr "  char *r;\n"; "NULL"
9069         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
9070         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
9071         | RStructList (_, typ) ->
9072             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
9073         | RBufferOut _ ->
9074             pr "  char *r;\n";
9075             pr "  size_t size;\n";
9076             "NULL" in
9077
9078       List.iter (
9079         function
9080         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9081             pr "  const char *%s;\n" n
9082         | OptString n -> pr "  const char *%s;\n" n
9083         | StringList n | DeviceList n ->
9084             pr "  PyObject *py_%s;\n" n;
9085             pr "  char **%s;\n" n
9086         | Bool n -> pr "  int %s;\n" n
9087         | Int n -> pr "  int %s;\n" n
9088         | Int64 n -> pr "  long long %s;\n" n
9089       ) (snd style);
9090
9091       pr "\n";
9092
9093       (* Convert the parameters. *)
9094       pr "  if (!PyArg_ParseTuple (args, (char *) \"O";
9095       List.iter (
9096         function
9097         | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
9098         | OptString _ -> pr "z"
9099         | StringList _ | DeviceList _ -> pr "O"
9100         | Bool _ -> pr "i" (* XXX Python has booleans? *)
9101         | Int _ -> pr "i"
9102         | Int64 _ -> pr "L" (* XXX Whoever thought it was a good idea to
9103                              * emulate C's int/long/long long in Python?
9104                              *)
9105       ) (snd style);
9106       pr ":guestfs_%s\",\n" name;
9107       pr "                         &py_g";
9108       List.iter (
9109         function
9110         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
9111         | OptString n -> pr ", &%s" n
9112         | StringList n | DeviceList n -> pr ", &py_%s" n
9113         | Bool n -> pr ", &%s" n
9114         | Int n -> pr ", &%s" n
9115         | Int64 n -> pr ", &%s" n
9116       ) (snd style);
9117
9118       pr "))\n";
9119       pr "    return NULL;\n";
9120
9121       pr "  g = get_handle (py_g);\n";
9122       List.iter (
9123         function
9124         | Pathname _ | Device _ | Dev_or_Path _ | String _
9125         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9126         | StringList n | DeviceList n ->
9127             pr "  %s = get_string_list (py_%s);\n" n n;
9128             pr "  if (!%s) return NULL;\n" n
9129       ) (snd style);
9130
9131       pr "\n";
9132
9133       pr "  r = guestfs_%s " name;
9134       generate_c_call_args ~handle:"g" style;
9135       pr ";\n";
9136
9137       List.iter (
9138         function
9139         | Pathname _ | Device _ | Dev_or_Path _ | String _
9140         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9141         | StringList n | DeviceList n ->
9142             pr "  free (%s);\n" n
9143       ) (snd style);
9144
9145       pr "  if (r == %s) {\n" error_code;
9146       pr "    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
9147       pr "    return NULL;\n";
9148       pr "  }\n";
9149       pr "\n";
9150
9151       (match fst style with
9152        | RErr ->
9153            pr "  Py_INCREF (Py_None);\n";
9154            pr "  py_r = Py_None;\n"
9155        | RInt _
9156        | RBool _ -> pr "  py_r = PyInt_FromLong ((long) r);\n"
9157        | RInt64 _ -> pr "  py_r = PyLong_FromLongLong (r);\n"
9158        | RConstString _ -> pr "  py_r = PyString_FromString (r);\n"
9159        | RConstOptString _ ->
9160            pr "  if (r)\n";
9161            pr "    py_r = PyString_FromString (r);\n";
9162            pr "  else {\n";
9163            pr "    Py_INCREF (Py_None);\n";
9164            pr "    py_r = Py_None;\n";
9165            pr "  }\n"
9166        | RString _ ->
9167            pr "  py_r = PyString_FromString (r);\n";
9168            pr "  free (r);\n"
9169        | RStringList _ ->
9170            pr "  py_r = put_string_list (r);\n";
9171            pr "  free_strings (r);\n"
9172        | RStruct (_, typ) ->
9173            pr "  py_r = put_%s (r);\n" typ;
9174            pr "  guestfs_free_%s (r);\n" typ
9175        | RStructList (_, typ) ->
9176            pr "  py_r = put_%s_list (r);\n" typ;
9177            pr "  guestfs_free_%s_list (r);\n" typ
9178        | RHashtable n ->
9179            pr "  py_r = put_table (r);\n";
9180            pr "  free_strings (r);\n"
9181        | RBufferOut _ ->
9182            pr "  py_r = PyString_FromStringAndSize (r, size);\n";
9183            pr "  free (r);\n"
9184       );
9185
9186       pr "  return py_r;\n";
9187       pr "}\n";
9188       pr "\n"
9189   ) all_functions;
9190
9191   (* Table of functions. *)
9192   pr "static PyMethodDef methods[] = {\n";
9193   pr "  { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
9194   pr "  { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
9195   List.iter (
9196     fun (name, _, _, _, _, _, _) ->
9197       pr "  { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
9198         name name
9199   ) all_functions;
9200   pr "  { NULL, NULL, 0, NULL }\n";
9201   pr "};\n";
9202   pr "\n";
9203
9204   (* Init function. *)
9205   pr "\
9206 void
9207 initlibguestfsmod (void)
9208 {
9209   static int initialized = 0;
9210
9211   if (initialized) return;
9212   Py_InitModule ((char *) \"libguestfsmod\", methods);
9213   initialized = 1;
9214 }
9215 "
9216
9217 (* Generate Python module. *)
9218 and generate_python_py () =
9219   generate_header HashStyle LGPLv2plus;
9220
9221   pr "\
9222 u\"\"\"Python bindings for libguestfs
9223
9224 import guestfs
9225 g = guestfs.GuestFS ()
9226 g.add_drive (\"guest.img\")
9227 g.launch ()
9228 parts = g.list_partitions ()
9229
9230 The guestfs module provides a Python binding to the libguestfs API
9231 for examining and modifying virtual machine disk images.
9232
9233 Amongst the things this is good for: making batch configuration
9234 changes to guests, getting disk used/free statistics (see also:
9235 virt-df), migrating between virtualization systems (see also:
9236 virt-p2v), performing partial backups, performing partial guest
9237 clones, cloning guests and changing registry/UUID/hostname info, and
9238 much else besides.
9239
9240 Libguestfs uses Linux kernel and qemu code, and can access any type of
9241 guest filesystem that Linux and qemu can, including but not limited
9242 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
9243 schemes, qcow, qcow2, vmdk.
9244
9245 Libguestfs provides ways to enumerate guest storage (eg. partitions,
9246 LVs, what filesystem is in each LV, etc.).  It can also run commands
9247 in the context of the guest.  Also you can access filesystems over
9248 FUSE.
9249
9250 Errors which happen while using the API are turned into Python
9251 RuntimeError exceptions.
9252
9253 To create a guestfs handle you usually have to perform the following
9254 sequence of calls:
9255
9256 # Create the handle, call add_drive at least once, and possibly
9257 # several times if the guest has multiple block devices:
9258 g = guestfs.GuestFS ()
9259 g.add_drive (\"guest.img\")
9260
9261 # Launch the qemu subprocess and wait for it to become ready:
9262 g.launch ()
9263
9264 # Now you can issue commands, for example:
9265 logvols = g.lvs ()
9266
9267 \"\"\"
9268
9269 import libguestfsmod
9270
9271 class GuestFS:
9272     \"\"\"Instances of this class are libguestfs API handles.\"\"\"
9273
9274     def __init__ (self):
9275         \"\"\"Create a new libguestfs handle.\"\"\"
9276         self._o = libguestfsmod.create ()
9277
9278     def __del__ (self):
9279         libguestfsmod.close (self._o)
9280
9281 ";
9282
9283   List.iter (
9284     fun (name, style, _, flags, _, _, longdesc) ->
9285       pr "    def %s " name;
9286       generate_py_call_args ~handle:"self" (snd style);
9287       pr ":\n";
9288
9289       if not (List.mem NotInDocs flags) then (
9290         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9291         let doc =
9292           match fst style with
9293           | RErr | RInt _ | RInt64 _ | RBool _
9294           | RConstOptString _ | RConstString _
9295           | RString _ | RBufferOut _ -> doc
9296           | RStringList _ ->
9297               doc ^ "\n\nThis function returns a list of strings."
9298           | RStruct (_, typ) ->
9299               doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
9300           | RStructList (_, typ) ->
9301               doc ^ sprintf "\n\nThis function returns a list of %ss.  Each %s is represented as a dictionary." typ typ
9302           | RHashtable _ ->
9303               doc ^ "\n\nThis function returns a dictionary." in
9304         let doc =
9305           if List.mem ProtocolLimitWarning flags then
9306             doc ^ "\n\n" ^ protocol_limit_warning
9307           else doc in
9308         let doc =
9309           if List.mem DangerWillRobinson flags then
9310             doc ^ "\n\n" ^ danger_will_robinson
9311           else doc in
9312         let doc =
9313           match deprecation_notice flags with
9314           | None -> doc
9315           | Some txt -> doc ^ "\n\n" ^ txt in
9316         let doc = pod2text ~width:60 name doc in
9317         let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
9318         let doc = String.concat "\n        " doc in
9319         pr "        u\"\"\"%s\"\"\"\n" doc;
9320       );
9321       pr "        return libguestfsmod.%s " name;
9322       generate_py_call_args ~handle:"self._o" (snd style);
9323       pr "\n";
9324       pr "\n";
9325   ) all_functions
9326
9327 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
9328 and generate_py_call_args ~handle args =
9329   pr "(%s" handle;
9330   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9331   pr ")"
9332
9333 (* Useful if you need the longdesc POD text as plain text.  Returns a
9334  * list of lines.
9335  *
9336  * Because this is very slow (the slowest part of autogeneration),
9337  * we memoize the results.
9338  *)
9339 and pod2text ~width name longdesc =
9340   let key = width, name, longdesc in
9341   try Hashtbl.find pod2text_memo key
9342   with Not_found ->
9343     let filename, chan = Filename.open_temp_file "gen" ".tmp" in
9344     fprintf chan "=head1 %s\n\n%s\n" name longdesc;
9345     close_out chan;
9346     let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
9347     let chan = open_process_in cmd in
9348     let lines = ref [] in
9349     let rec loop i =
9350       let line = input_line chan in
9351       if i = 1 then             (* discard the first line of output *)
9352         loop (i+1)
9353       else (
9354         let line = triml line in
9355         lines := line :: !lines;
9356         loop (i+1)
9357       ) in
9358     let lines = try loop 1 with End_of_file -> List.rev !lines in
9359     unlink filename;
9360     (match close_process_in chan with
9361      | WEXITED 0 -> ()
9362      | WEXITED i ->
9363          failwithf "pod2text: process exited with non-zero status (%d)" i
9364      | WSIGNALED i | WSTOPPED i ->
9365          failwithf "pod2text: process signalled or stopped by signal %d" i
9366     );
9367     Hashtbl.add pod2text_memo key lines;
9368     pod2text_memo_updated ();
9369     lines
9370
9371 (* Generate ruby bindings. *)
9372 and generate_ruby_c () =
9373   generate_header CStyle LGPLv2plus;
9374
9375   pr "\
9376 #include <stdio.h>
9377 #include <stdlib.h>
9378
9379 #include <ruby.h>
9380
9381 #include \"guestfs.h\"
9382
9383 #include \"extconf.h\"
9384
9385 /* For Ruby < 1.9 */
9386 #ifndef RARRAY_LEN
9387 #define RARRAY_LEN(r) (RARRAY((r))->len)
9388 #endif
9389
9390 static VALUE m_guestfs;                 /* guestfs module */
9391 static VALUE c_guestfs;                 /* guestfs_h handle */
9392 static VALUE e_Error;                   /* used for all errors */
9393
9394 static void ruby_guestfs_free (void *p)
9395 {
9396   if (!p) return;
9397   guestfs_close ((guestfs_h *) p);
9398 }
9399
9400 static VALUE ruby_guestfs_create (VALUE m)
9401 {
9402   guestfs_h *g;
9403
9404   g = guestfs_create ();
9405   if (!g)
9406     rb_raise (e_Error, \"failed to create guestfs handle\");
9407
9408   /* Don't print error messages to stderr by default. */
9409   guestfs_set_error_handler (g, NULL, NULL);
9410
9411   /* Wrap it, and make sure the close function is called when the
9412    * handle goes away.
9413    */
9414   return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
9415 }
9416
9417 static VALUE ruby_guestfs_close (VALUE gv)
9418 {
9419   guestfs_h *g;
9420   Data_Get_Struct (gv, guestfs_h, g);
9421
9422   ruby_guestfs_free (g);
9423   DATA_PTR (gv) = NULL;
9424
9425   return Qnil;
9426 }
9427
9428 ";
9429
9430   List.iter (
9431     fun (name, style, _, _, _, _, _) ->
9432       pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
9433       List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
9434       pr ")\n";
9435       pr "{\n";
9436       pr "  guestfs_h *g;\n";
9437       pr "  Data_Get_Struct (gv, guestfs_h, g);\n";
9438       pr "  if (!g)\n";
9439       pr "    rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
9440         name;
9441       pr "\n";
9442
9443       List.iter (
9444         function
9445         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9446             pr "  Check_Type (%sv, T_STRING);\n" n;
9447             pr "  const char *%s = StringValueCStr (%sv);\n" n n;
9448             pr "  if (!%s)\n" n;
9449             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
9450             pr "              \"%s\", \"%s\");\n" n name
9451         | OptString n ->
9452             pr "  const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
9453         | StringList n | DeviceList n ->
9454             pr "  char **%s;\n" n;
9455             pr "  Check_Type (%sv, T_ARRAY);\n" n;
9456             pr "  {\n";
9457             pr "    int i, len;\n";
9458             pr "    len = RARRAY_LEN (%sv);\n" n;
9459             pr "    %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
9460               n;
9461             pr "    for (i = 0; i < len; ++i) {\n";
9462             pr "      VALUE v = rb_ary_entry (%sv, i);\n" n;
9463             pr "      %s[i] = StringValueCStr (v);\n" n;
9464             pr "    }\n";
9465             pr "    %s[len] = NULL;\n" n;
9466             pr "  }\n";
9467         | Bool n ->
9468             pr "  int %s = RTEST (%sv);\n" n n
9469         | Int n ->
9470             pr "  int %s = NUM2INT (%sv);\n" n n
9471         | Int64 n ->
9472             pr "  long long %s = NUM2LL (%sv);\n" n n
9473       ) (snd style);
9474       pr "\n";
9475
9476       let error_code =
9477         match fst style with
9478         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
9479         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
9480         | RConstString _ | RConstOptString _ ->
9481             pr "  const char *r;\n"; "NULL"
9482         | RString _ -> pr "  char *r;\n"; "NULL"
9483         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
9484         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
9485         | RStructList (_, typ) ->
9486             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
9487         | RBufferOut _ ->
9488             pr "  char *r;\n";
9489             pr "  size_t size;\n";
9490             "NULL" in
9491       pr "\n";
9492
9493       pr "  r = guestfs_%s " name;
9494       generate_c_call_args ~handle:"g" style;
9495       pr ";\n";
9496
9497       List.iter (
9498         function
9499         | Pathname _ | Device _ | Dev_or_Path _ | String _
9500         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9501         | StringList n | DeviceList n ->
9502             pr "  free (%s);\n" n
9503       ) (snd style);
9504
9505       pr "  if (r == %s)\n" error_code;
9506       pr "    rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
9507       pr "\n";
9508
9509       (match fst style with
9510        | RErr ->
9511            pr "  return Qnil;\n"
9512        | RInt _ | RBool _ ->
9513            pr "  return INT2NUM (r);\n"
9514        | RInt64 _ ->
9515            pr "  return ULL2NUM (r);\n"
9516        | RConstString _ ->
9517            pr "  return rb_str_new2 (r);\n";
9518        | RConstOptString _ ->
9519            pr "  if (r)\n";
9520            pr "    return rb_str_new2 (r);\n";
9521            pr "  else\n";
9522            pr "    return Qnil;\n";
9523        | RString _ ->
9524            pr "  VALUE rv = rb_str_new2 (r);\n";
9525            pr "  free (r);\n";
9526            pr "  return rv;\n";
9527        | RStringList _ ->
9528            pr "  int i, len = 0;\n";
9529            pr "  for (i = 0; r[i] != NULL; ++i) len++;\n";
9530            pr "  VALUE rv = rb_ary_new2 (len);\n";
9531            pr "  for (i = 0; r[i] != NULL; ++i) {\n";
9532            pr "    rb_ary_push (rv, rb_str_new2 (r[i]));\n";
9533            pr "    free (r[i]);\n";
9534            pr "  }\n";
9535            pr "  free (r);\n";
9536            pr "  return rv;\n"
9537        | RStruct (_, typ) ->
9538            let cols = cols_of_struct typ in
9539            generate_ruby_struct_code typ cols
9540        | RStructList (_, typ) ->
9541            let cols = cols_of_struct typ in
9542            generate_ruby_struct_list_code typ cols
9543        | RHashtable _ ->
9544            pr "  VALUE rv = rb_hash_new ();\n";
9545            pr "  int i;\n";
9546            pr "  for (i = 0; r[i] != NULL; i+=2) {\n";
9547            pr "    rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
9548            pr "    free (r[i]);\n";
9549            pr "    free (r[i+1]);\n";
9550            pr "  }\n";
9551            pr "  free (r);\n";
9552            pr "  return rv;\n"
9553        | RBufferOut _ ->
9554            pr "  VALUE rv = rb_str_new (r, size);\n";
9555            pr "  free (r);\n";
9556            pr "  return rv;\n";
9557       );
9558
9559       pr "}\n";
9560       pr "\n"
9561   ) all_functions;
9562
9563   pr "\
9564 /* Initialize the module. */
9565 void Init__guestfs ()
9566 {
9567   m_guestfs = rb_define_module (\"Guestfs\");
9568   c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
9569   e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
9570
9571   rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
9572   rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
9573
9574 ";
9575   (* Define the rest of the methods. *)
9576   List.iter (
9577     fun (name, style, _, _, _, _, _) ->
9578       pr "  rb_define_method (c_guestfs, \"%s\",\n" name;
9579       pr "        ruby_guestfs_%s, %d);\n" name (List.length (snd style))
9580   ) all_functions;
9581
9582   pr "}\n"
9583
9584 (* Ruby code to return a struct. *)
9585 and generate_ruby_struct_code typ cols =
9586   pr "  VALUE rv = rb_hash_new ();\n";
9587   List.iter (
9588     function
9589     | name, FString ->
9590         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
9591     | name, FBuffer ->
9592         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
9593     | name, FUUID ->
9594         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
9595     | name, (FBytes|FUInt64) ->
9596         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9597     | name, FInt64 ->
9598         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
9599     | name, FUInt32 ->
9600         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
9601     | name, FInt32 ->
9602         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
9603     | name, FOptPercent ->
9604         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
9605     | name, FChar -> (* XXX wrong? *)
9606         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9607   ) cols;
9608   pr "  guestfs_free_%s (r);\n" typ;
9609   pr "  return rv;\n"
9610
9611 (* Ruby code to return a struct list. *)
9612 and generate_ruby_struct_list_code typ cols =
9613   pr "  VALUE rv = rb_ary_new2 (r->len);\n";
9614   pr "  int i;\n";
9615   pr "  for (i = 0; i < r->len; ++i) {\n";
9616   pr "    VALUE hv = rb_hash_new ();\n";
9617   List.iter (
9618     function
9619     | name, FString ->
9620         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
9621     | name, FBuffer ->
9622         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
9623     | name, FUUID ->
9624         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
9625     | name, (FBytes|FUInt64) ->
9626         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9627     | name, FInt64 ->
9628         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
9629     | name, FUInt32 ->
9630         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
9631     | name, FInt32 ->
9632         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
9633     | name, FOptPercent ->
9634         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
9635     | name, FChar -> (* XXX wrong? *)
9636         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9637   ) cols;
9638   pr "    rb_ary_push (rv, hv);\n";
9639   pr "  }\n";
9640   pr "  guestfs_free_%s_list (r);\n" typ;
9641   pr "  return rv;\n"
9642
9643 (* Generate Java bindings GuestFS.java file. *)
9644 and generate_java_java () =
9645   generate_header CStyle LGPLv2plus;
9646
9647   pr "\
9648 package com.redhat.et.libguestfs;
9649
9650 import java.util.HashMap;
9651 import com.redhat.et.libguestfs.LibGuestFSException;
9652 import com.redhat.et.libguestfs.PV;
9653 import com.redhat.et.libguestfs.VG;
9654 import com.redhat.et.libguestfs.LV;
9655 import com.redhat.et.libguestfs.Stat;
9656 import com.redhat.et.libguestfs.StatVFS;
9657 import com.redhat.et.libguestfs.IntBool;
9658 import com.redhat.et.libguestfs.Dirent;
9659
9660 /**
9661  * The GuestFS object is a libguestfs handle.
9662  *
9663  * @author rjones
9664  */
9665 public class GuestFS {
9666   // Load the native code.
9667   static {
9668     System.loadLibrary (\"guestfs_jni\");
9669   }
9670
9671   /**
9672    * The native guestfs_h pointer.
9673    */
9674   long g;
9675
9676   /**
9677    * Create a libguestfs handle.
9678    *
9679    * @throws LibGuestFSException
9680    */
9681   public GuestFS () throws LibGuestFSException
9682   {
9683     g = _create ();
9684   }
9685   private native long _create () throws LibGuestFSException;
9686
9687   /**
9688    * Close a libguestfs handle.
9689    *
9690    * You can also leave handles to be collected by the garbage
9691    * collector, but this method ensures that the resources used
9692    * by the handle are freed up immediately.  If you call any
9693    * other methods after closing the handle, you will get an
9694    * exception.
9695    *
9696    * @throws LibGuestFSException
9697    */
9698   public void close () throws LibGuestFSException
9699   {
9700     if (g != 0)
9701       _close (g);
9702     g = 0;
9703   }
9704   private native void _close (long g) throws LibGuestFSException;
9705
9706   public void finalize () throws LibGuestFSException
9707   {
9708     close ();
9709   }
9710
9711 ";
9712
9713   List.iter (
9714     fun (name, style, _, flags, _, shortdesc, longdesc) ->
9715       if not (List.mem NotInDocs flags); then (
9716         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9717         let doc =
9718           if List.mem ProtocolLimitWarning flags then
9719             doc ^ "\n\n" ^ protocol_limit_warning
9720           else doc in
9721         let doc =
9722           if List.mem DangerWillRobinson flags then
9723             doc ^ "\n\n" ^ danger_will_robinson
9724           else doc in
9725         let doc =
9726           match deprecation_notice flags with
9727           | None -> doc
9728           | Some txt -> doc ^ "\n\n" ^ txt in
9729         let doc = pod2text ~width:60 name doc in
9730         let doc = List.map (            (* RHBZ#501883 *)
9731           function
9732           | "" -> "<p>"
9733           | nonempty -> nonempty
9734         ) doc in
9735         let doc = String.concat "\n   * " doc in
9736
9737         pr "  /**\n";
9738         pr "   * %s\n" shortdesc;
9739         pr "   * <p>\n";
9740         pr "   * %s\n" doc;
9741         pr "   * @throws LibGuestFSException\n";
9742         pr "   */\n";
9743         pr "  ";
9744       );
9745       generate_java_prototype ~public:true ~semicolon:false name style;
9746       pr "\n";
9747       pr "  {\n";
9748       pr "    if (g == 0)\n";
9749       pr "      throw new LibGuestFSException (\"%s: handle is closed\");\n"
9750         name;
9751       pr "    ";
9752       if fst style <> RErr then pr "return ";
9753       pr "_%s " name;
9754       generate_java_call_args ~handle:"g" (snd style);
9755       pr ";\n";
9756       pr "  }\n";
9757       pr "  ";
9758       generate_java_prototype ~privat:true ~native:true name style;
9759       pr "\n";
9760       pr "\n";
9761   ) all_functions;
9762
9763   pr "}\n"
9764
9765 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
9766 and generate_java_call_args ~handle args =
9767   pr "(%s" handle;
9768   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9769   pr ")"
9770
9771 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
9772     ?(semicolon=true) name style =
9773   if privat then pr "private ";
9774   if public then pr "public ";
9775   if native then pr "native ";
9776
9777   (* return type *)
9778   (match fst style with
9779    | RErr -> pr "void ";
9780    | RInt _ -> pr "int ";
9781    | RInt64 _ -> pr "long ";
9782    | RBool _ -> pr "boolean ";
9783    | RConstString _ | RConstOptString _ | RString _
9784    | RBufferOut _ -> pr "String ";
9785    | RStringList _ -> pr "String[] ";
9786    | RStruct (_, typ) ->
9787        let name = java_name_of_struct typ in
9788        pr "%s " name;
9789    | RStructList (_, typ) ->
9790        let name = java_name_of_struct typ in
9791        pr "%s[] " name;
9792    | RHashtable _ -> pr "HashMap<String,String> ";
9793   );
9794
9795   if native then pr "_%s " name else pr "%s " name;
9796   pr "(";
9797   let needs_comma = ref false in
9798   if native then (
9799     pr "long g";
9800     needs_comma := true
9801   );
9802
9803   (* args *)
9804   List.iter (
9805     fun arg ->
9806       if !needs_comma then pr ", ";
9807       needs_comma := true;
9808
9809       match arg with
9810       | Pathname n
9811       | Device n | Dev_or_Path n
9812       | String n
9813       | OptString n
9814       | FileIn n
9815       | FileOut n ->
9816           pr "String %s" n
9817       | StringList n | DeviceList n ->
9818           pr "String[] %s" n
9819       | Bool n ->
9820           pr "boolean %s" n
9821       | Int n ->
9822           pr "int %s" n
9823       | Int64 n ->
9824           pr "long %s" n
9825   ) (snd style);
9826
9827   pr ")\n";
9828   pr "    throws LibGuestFSException";
9829   if semicolon then pr ";"
9830
9831 and generate_java_struct jtyp cols () =
9832   generate_header CStyle LGPLv2plus;
9833
9834   pr "\
9835 package com.redhat.et.libguestfs;
9836
9837 /**
9838  * Libguestfs %s structure.
9839  *
9840  * @author rjones
9841  * @see GuestFS
9842  */
9843 public class %s {
9844 " jtyp jtyp;
9845
9846   List.iter (
9847     function
9848     | name, FString
9849     | name, FUUID
9850     | name, FBuffer -> pr "  public String %s;\n" name
9851     | name, (FBytes|FUInt64|FInt64) -> pr "  public long %s;\n" name
9852     | name, (FUInt32|FInt32) -> pr "  public int %s;\n" name
9853     | name, FChar -> pr "  public char %s;\n" name
9854     | name, FOptPercent ->
9855         pr "  /* The next field is [0..100] or -1 meaning 'not present': */\n";
9856         pr "  public float %s;\n" name
9857   ) cols;
9858
9859   pr "}\n"
9860
9861 and generate_java_c () =
9862   generate_header CStyle LGPLv2plus;
9863
9864   pr "\
9865 #include <stdio.h>
9866 #include <stdlib.h>
9867 #include <string.h>
9868
9869 #include \"com_redhat_et_libguestfs_GuestFS.h\"
9870 #include \"guestfs.h\"
9871
9872 /* Note that this function returns.  The exception is not thrown
9873  * until after the wrapper function returns.
9874  */
9875 static void
9876 throw_exception (JNIEnv *env, const char *msg)
9877 {
9878   jclass cl;
9879   cl = (*env)->FindClass (env,
9880                           \"com/redhat/et/libguestfs/LibGuestFSException\");
9881   (*env)->ThrowNew (env, cl, msg);
9882 }
9883
9884 JNIEXPORT jlong JNICALL
9885 Java_com_redhat_et_libguestfs_GuestFS__1create
9886   (JNIEnv *env, jobject obj)
9887 {
9888   guestfs_h *g;
9889
9890   g = guestfs_create ();
9891   if (g == NULL) {
9892     throw_exception (env, \"GuestFS.create: failed to allocate handle\");
9893     return 0;
9894   }
9895   guestfs_set_error_handler (g, NULL, NULL);
9896   return (jlong) (long) g;
9897 }
9898
9899 JNIEXPORT void JNICALL
9900 Java_com_redhat_et_libguestfs_GuestFS__1close
9901   (JNIEnv *env, jobject obj, jlong jg)
9902 {
9903   guestfs_h *g = (guestfs_h *) (long) jg;
9904   guestfs_close (g);
9905 }
9906
9907 ";
9908
9909   List.iter (
9910     fun (name, style, _, _, _, _, _) ->
9911       pr "JNIEXPORT ";
9912       (match fst style with
9913        | RErr -> pr "void ";
9914        | RInt _ -> pr "jint ";
9915        | RInt64 _ -> pr "jlong ";
9916        | RBool _ -> pr "jboolean ";
9917        | RConstString _ | RConstOptString _ | RString _
9918        | RBufferOut _ -> pr "jstring ";
9919        | RStruct _ | RHashtable _ ->
9920            pr "jobject ";
9921        | RStringList _ | RStructList _ ->
9922            pr "jobjectArray ";
9923       );
9924       pr "JNICALL\n";
9925       pr "Java_com_redhat_et_libguestfs_GuestFS_";
9926       pr "%s" (replace_str ("_" ^ name) "_" "_1");
9927       pr "\n";
9928       pr "  (JNIEnv *env, jobject obj, jlong jg";
9929       List.iter (
9930         function
9931         | Pathname n
9932         | Device n | Dev_or_Path n
9933         | String n
9934         | OptString n
9935         | FileIn n
9936         | FileOut n ->
9937             pr ", jstring j%s" n
9938         | StringList n | DeviceList n ->
9939             pr ", jobjectArray j%s" n
9940         | Bool n ->
9941             pr ", jboolean j%s" n
9942         | Int n ->
9943             pr ", jint j%s" n
9944         | Int64 n ->
9945             pr ", jlong j%s" n
9946       ) (snd style);
9947       pr ")\n";
9948       pr "{\n";
9949       pr "  guestfs_h *g = (guestfs_h *) (long) jg;\n";
9950       let error_code, no_ret =
9951         match fst style with
9952         | RErr -> pr "  int r;\n"; "-1", ""
9953         | RBool _
9954         | RInt _ -> pr "  int r;\n"; "-1", "0"
9955         | RInt64 _ -> pr "  int64_t r;\n"; "-1", "0"
9956         | RConstString _ -> pr "  const char *r;\n"; "NULL", "NULL"
9957         | RConstOptString _ -> pr "  const char *r;\n"; "NULL", "NULL"
9958         | RString _ ->
9959             pr "  jstring jr;\n";
9960             pr "  char *r;\n"; "NULL", "NULL"
9961         | RStringList _ ->
9962             pr "  jobjectArray jr;\n";
9963             pr "  int r_len;\n";
9964             pr "  jclass cl;\n";
9965             pr "  jstring jstr;\n";
9966             pr "  char **r;\n"; "NULL", "NULL"
9967         | RStruct (_, typ) ->
9968             pr "  jobject jr;\n";
9969             pr "  jclass cl;\n";
9970             pr "  jfieldID fl;\n";
9971             pr "  struct guestfs_%s *r;\n" typ; "NULL", "NULL"
9972         | RStructList (_, typ) ->
9973             pr "  jobjectArray jr;\n";
9974             pr "  jclass cl;\n";
9975             pr "  jfieldID fl;\n";
9976             pr "  jobject jfl;\n";
9977             pr "  struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
9978         | RHashtable _ -> pr "  char **r;\n"; "NULL", "NULL"
9979         | RBufferOut _ ->
9980             pr "  jstring jr;\n";
9981             pr "  char *r;\n";
9982             pr "  size_t size;\n";
9983             "NULL", "NULL" in
9984       List.iter (
9985         function
9986         | Pathname n
9987         | Device n | Dev_or_Path n
9988         | String n
9989         | OptString n
9990         | FileIn n
9991         | FileOut n ->
9992             pr "  const char *%s;\n" n
9993         | StringList n | DeviceList n ->
9994             pr "  int %s_len;\n" n;
9995             pr "  const char **%s;\n" n
9996         | Bool n
9997         | Int n ->
9998             pr "  int %s;\n" n
9999         | Int64 n ->
10000             pr "  int64_t %s;\n" n
10001       ) (snd style);
10002
10003       let needs_i =
10004         (match fst style with
10005          | RStringList _ | RStructList _ -> true
10006          | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
10007          | RConstOptString _
10008          | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
10009           List.exists (function
10010                        | StringList _ -> true
10011                        | DeviceList _ -> true
10012                        | _ -> false) (snd style) in
10013       if needs_i then
10014         pr "  int i;\n";
10015
10016       pr "\n";
10017
10018       (* Get the parameters. *)
10019       List.iter (
10020         function
10021         | Pathname n
10022         | Device n | Dev_or_Path n
10023         | String n
10024         | FileIn n
10025         | FileOut n ->
10026             pr "  %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
10027         | OptString n ->
10028             (* This is completely undocumented, but Java null becomes
10029              * a NULL parameter.
10030              *)
10031             pr "  %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
10032         | StringList n | DeviceList n ->
10033             pr "  %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
10034             pr "  %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
10035             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
10036             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
10037               n;
10038             pr "    %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
10039             pr "  }\n";
10040             pr "  %s[%s_len] = NULL;\n" n n;
10041         | Bool n
10042         | Int n
10043         | Int64 n ->
10044             pr "  %s = j%s;\n" n n
10045       ) (snd style);
10046
10047       (* Make the call. *)
10048       pr "  r = guestfs_%s " name;
10049       generate_c_call_args ~handle:"g" style;
10050       pr ";\n";
10051
10052       (* Release the parameters. *)
10053       List.iter (
10054         function
10055         | Pathname n
10056         | Device n | Dev_or_Path n
10057         | String n
10058         | FileIn n
10059         | FileOut n ->
10060             pr "  (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
10061         | OptString n ->
10062             pr "  if (j%s)\n" n;
10063             pr "    (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
10064         | StringList n | DeviceList n ->
10065             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
10066             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
10067               n;
10068             pr "    (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
10069             pr "  }\n";
10070             pr "  free (%s);\n" n
10071         | Bool n
10072         | Int n
10073         | Int64 n -> ()
10074       ) (snd style);
10075
10076       (* Check for errors. *)
10077       pr "  if (r == %s) {\n" error_code;
10078       pr "    throw_exception (env, guestfs_last_error (g));\n";
10079       pr "    return %s;\n" no_ret;
10080       pr "  }\n";
10081
10082       (* Return value. *)
10083       (match fst style with
10084        | RErr -> ()
10085        | RInt _ -> pr "  return (jint) r;\n"
10086        | RBool _ -> pr "  return (jboolean) r;\n"
10087        | RInt64 _ -> pr "  return (jlong) r;\n"
10088        | RConstString _ -> pr "  return (*env)->NewStringUTF (env, r);\n"
10089        | RConstOptString _ ->
10090            pr "  return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
10091        | RString _ ->
10092            pr "  jr = (*env)->NewStringUTF (env, r);\n";
10093            pr "  free (r);\n";
10094            pr "  return jr;\n"
10095        | RStringList _ ->
10096            pr "  for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
10097            pr "  cl = (*env)->FindClass (env, \"java/lang/String\");\n";
10098            pr "  jstr = (*env)->NewStringUTF (env, \"\");\n";
10099            pr "  jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
10100            pr "  for (i = 0; i < r_len; ++i) {\n";
10101            pr "    jstr = (*env)->NewStringUTF (env, r[i]);\n";
10102            pr "    (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
10103            pr "    free (r[i]);\n";
10104            pr "  }\n";
10105            pr "  free (r);\n";
10106            pr "  return jr;\n"
10107        | RStruct (_, typ) ->
10108            let jtyp = java_name_of_struct typ in
10109            let cols = cols_of_struct typ in
10110            generate_java_struct_return typ jtyp cols
10111        | RStructList (_, typ) ->
10112            let jtyp = java_name_of_struct typ in
10113            let cols = cols_of_struct typ in
10114            generate_java_struct_list_return typ jtyp cols
10115        | RHashtable _ ->
10116            (* XXX *)
10117            pr "  throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
10118            pr "  return NULL;\n"
10119        | RBufferOut _ ->
10120            pr "  jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
10121            pr "  free (r);\n";
10122            pr "  return jr;\n"
10123       );
10124
10125       pr "}\n";
10126       pr "\n"
10127   ) all_functions
10128
10129 and generate_java_struct_return typ jtyp cols =
10130   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10131   pr "  jr = (*env)->AllocObject (env, cl);\n";
10132   List.iter (
10133     function
10134     | name, FString ->
10135         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10136         pr "  (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
10137     | name, FUUID ->
10138         pr "  {\n";
10139         pr "    char s[33];\n";
10140         pr "    memcpy (s, r->%s, 32);\n" name;
10141         pr "    s[32] = 0;\n";
10142         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10143         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10144         pr "  }\n";
10145     | name, FBuffer ->
10146         pr "  {\n";
10147         pr "    int len = r->%s_len;\n" name;
10148         pr "    char s[len+1];\n";
10149         pr "    memcpy (s, r->%s, len);\n" name;
10150         pr "    s[len] = 0;\n";
10151         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10152         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10153         pr "  }\n";
10154     | name, (FBytes|FUInt64|FInt64) ->
10155         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10156         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10157     | name, (FUInt32|FInt32) ->
10158         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10159         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10160     | name, FOptPercent ->
10161         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10162         pr "  (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
10163     | name, FChar ->
10164         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10165         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10166   ) cols;
10167   pr "  free (r);\n";
10168   pr "  return jr;\n"
10169
10170 and generate_java_struct_list_return typ jtyp cols =
10171   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10172   pr "  jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
10173   pr "  for (i = 0; i < r->len; ++i) {\n";
10174   pr "    jfl = (*env)->AllocObject (env, cl);\n";
10175   List.iter (
10176     function
10177     | name, FString ->
10178         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10179         pr "    (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
10180     | name, FUUID ->
10181         pr "    {\n";
10182         pr "      char s[33];\n";
10183         pr "      memcpy (s, r->val[i].%s, 32);\n" name;
10184         pr "      s[32] = 0;\n";
10185         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10186         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10187         pr "    }\n";
10188     | name, FBuffer ->
10189         pr "    {\n";
10190         pr "      int len = r->val[i].%s_len;\n" name;
10191         pr "      char s[len+1];\n";
10192         pr "      memcpy (s, r->val[i].%s, len);\n" name;
10193         pr "      s[len] = 0;\n";
10194         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10195         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10196         pr "    }\n";
10197     | name, (FBytes|FUInt64|FInt64) ->
10198         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10199         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10200     | name, (FUInt32|FInt32) ->
10201         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10202         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10203     | name, FOptPercent ->
10204         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10205         pr "    (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
10206     | name, FChar ->
10207         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10208         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10209   ) cols;
10210   pr "    (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
10211   pr "  }\n";
10212   pr "  guestfs_free_%s_list (r);\n" typ;
10213   pr "  return jr;\n"
10214
10215 and generate_java_makefile_inc () =
10216   generate_header HashStyle GPLv2plus;
10217
10218   pr "java_built_sources = \\\n";
10219   List.iter (
10220     fun (typ, jtyp) ->
10221         pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
10222   ) java_structs;
10223   pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
10224
10225 and generate_haskell_hs () =
10226   generate_header HaskellStyle LGPLv2plus;
10227
10228   (* XXX We only know how to generate partial FFI for Haskell
10229    * at the moment.  Please help out!
10230    *)
10231   let can_generate style =
10232     match style with
10233     | RErr, _
10234     | RInt _, _
10235     | RInt64 _, _ -> true
10236     | RBool _, _
10237     | RConstString _, _
10238     | RConstOptString _, _
10239     | RString _, _
10240     | RStringList _, _
10241     | RStruct _, _
10242     | RStructList _, _
10243     | RHashtable _, _
10244     | RBufferOut _, _ -> false in
10245
10246   pr "\
10247 {-# INCLUDE <guestfs.h> #-}
10248 {-# LANGUAGE ForeignFunctionInterface #-}
10249
10250 module Guestfs (
10251   create";
10252
10253   (* List out the names of the actions we want to export. *)
10254   List.iter (
10255     fun (name, style, _, _, _, _, _) ->
10256       if can_generate style then pr ",\n  %s" name
10257   ) all_functions;
10258
10259   pr "
10260   ) where
10261
10262 -- Unfortunately some symbols duplicate ones already present
10263 -- in Prelude.  We don't know which, so we hard-code a list
10264 -- here.
10265 import Prelude hiding (truncate)
10266
10267 import Foreign
10268 import Foreign.C
10269 import Foreign.C.Types
10270 import IO
10271 import Control.Exception
10272 import Data.Typeable
10273
10274 data GuestfsS = GuestfsS            -- represents the opaque C struct
10275 type GuestfsP = Ptr GuestfsS        -- guestfs_h *
10276 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
10277
10278 -- XXX define properly later XXX
10279 data PV = PV
10280 data VG = VG
10281 data LV = LV
10282 data IntBool = IntBool
10283 data Stat = Stat
10284 data StatVFS = StatVFS
10285 data Hashtable = Hashtable
10286
10287 foreign import ccall unsafe \"guestfs_create\" c_create
10288   :: IO GuestfsP
10289 foreign import ccall unsafe \"&guestfs_close\" c_close
10290   :: FunPtr (GuestfsP -> IO ())
10291 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
10292   :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
10293
10294 create :: IO GuestfsH
10295 create = do
10296   p <- c_create
10297   c_set_error_handler p nullPtr nullPtr
10298   h <- newForeignPtr c_close p
10299   return h
10300
10301 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
10302   :: GuestfsP -> IO CString
10303
10304 -- last_error :: GuestfsH -> IO (Maybe String)
10305 -- last_error h = do
10306 --   str <- withForeignPtr h (\\p -> c_last_error p)
10307 --   maybePeek peekCString str
10308
10309 last_error :: GuestfsH -> IO (String)
10310 last_error h = do
10311   str <- withForeignPtr h (\\p -> c_last_error p)
10312   if (str == nullPtr)
10313     then return \"no error\"
10314     else peekCString str
10315
10316 ";
10317
10318   (* Generate wrappers for each foreign function. *)
10319   List.iter (
10320     fun (name, style, _, _, _, _, _) ->
10321       if can_generate style then (
10322         pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
10323         pr "  :: ";
10324         generate_haskell_prototype ~handle:"GuestfsP" style;
10325         pr "\n";
10326         pr "\n";
10327         pr "%s :: " name;
10328         generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
10329         pr "\n";
10330         pr "%s %s = do\n" name
10331           (String.concat " " ("h" :: List.map name_of_argt (snd style)));
10332         pr "  r <- ";
10333         (* Convert pointer arguments using with* functions. *)
10334         List.iter (
10335           function
10336           | FileIn n
10337           | FileOut n
10338           | Pathname n | Device n | Dev_or_Path n | String n -> pr "withCString %s $ \\%s -> " n n
10339           | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
10340           | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
10341           | Bool _ | Int _ | Int64 _ -> ()
10342         ) (snd style);
10343         (* Convert integer arguments. *)
10344         let args =
10345           List.map (
10346             function
10347             | Bool n -> sprintf "(fromBool %s)" n
10348             | Int n -> sprintf "(fromIntegral %s)" n
10349             | Int64 n -> sprintf "(fromIntegral %s)" n
10350             | FileIn n | FileOut n
10351             | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
10352           ) (snd style) in
10353         pr "withForeignPtr h (\\p -> c_%s %s)\n" name
10354           (String.concat " " ("p" :: args));
10355         (match fst style with
10356          | RErr | RInt _ | RInt64 _ | RBool _ ->
10357              pr "  if (r == -1)\n";
10358              pr "    then do\n";
10359              pr "      err <- last_error h\n";
10360              pr "      fail err\n";
10361          | RConstString _ | RConstOptString _ | RString _
10362          | RStringList _ | RStruct _
10363          | RStructList _ | RHashtable _ | RBufferOut _ ->
10364              pr "  if (r == nullPtr)\n";
10365              pr "    then do\n";
10366              pr "      err <- last_error h\n";
10367              pr "      fail err\n";
10368         );
10369         (match fst style with
10370          | RErr ->
10371              pr "    else return ()\n"
10372          | RInt _ ->
10373              pr "    else return (fromIntegral r)\n"
10374          | RInt64 _ ->
10375              pr "    else return (fromIntegral r)\n"
10376          | RBool _ ->
10377              pr "    else return (toBool r)\n"
10378          | RConstString _
10379          | RConstOptString _
10380          | RString _
10381          | RStringList _
10382          | RStruct _
10383          | RStructList _
10384          | RHashtable _
10385          | RBufferOut _ ->
10386              pr "    else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
10387         );
10388         pr "\n";
10389       )
10390   ) all_functions
10391
10392 and generate_haskell_prototype ~handle ?(hs = false) style =
10393   pr "%s -> " handle;
10394   let string = if hs then "String" else "CString" in
10395   let int = if hs then "Int" else "CInt" in
10396   let bool = if hs then "Bool" else "CInt" in
10397   let int64 = if hs then "Integer" else "Int64" in
10398   List.iter (
10399     fun arg ->
10400       (match arg with
10401        | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
10402        | OptString _ -> if hs then pr "Maybe String" else pr "CString"
10403        | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
10404        | Bool _ -> pr "%s" bool
10405        | Int _ -> pr "%s" int
10406        | Int64 _ -> pr "%s" int
10407        | FileIn _ -> pr "%s" string
10408        | FileOut _ -> pr "%s" string
10409       );
10410       pr " -> ";
10411   ) (snd style);
10412   pr "IO (";
10413   (match fst style with
10414    | RErr -> if not hs then pr "CInt"
10415    | RInt _ -> pr "%s" int
10416    | RInt64 _ -> pr "%s" int64
10417    | RBool _ -> pr "%s" bool
10418    | RConstString _ -> pr "%s" string
10419    | RConstOptString _ -> pr "Maybe %s" string
10420    | RString _ -> pr "%s" string
10421    | RStringList _ -> pr "[%s]" string
10422    | RStruct (_, typ) ->
10423        let name = java_name_of_struct typ in
10424        pr "%s" name
10425    | RStructList (_, typ) ->
10426        let name = java_name_of_struct typ in
10427        pr "[%s]" name
10428    | RHashtable _ -> pr "Hashtable"
10429    | RBufferOut _ -> pr "%s" string
10430   );
10431   pr ")"
10432
10433 and generate_csharp () =
10434   generate_header CPlusPlusStyle LGPLv2plus;
10435
10436   (* XXX Make this configurable by the C# assembly users. *)
10437   let library = "libguestfs.so.0" in
10438
10439   pr "\
10440 // These C# bindings are highly experimental at present.
10441 //
10442 // Firstly they only work on Linux (ie. Mono).  In order to get them
10443 // to work on Windows (ie. .Net) you would need to port the library
10444 // itself to Windows first.
10445 //
10446 // The second issue is that some calls are known to be incorrect and
10447 // can cause Mono to segfault.  Particularly: calls which pass or
10448 // return string[], or return any structure value.  This is because
10449 // we haven't worked out the correct way to do this from C#.
10450 //
10451 // The third issue is that when compiling you get a lot of warnings.
10452 // We are not sure whether the warnings are important or not.
10453 //
10454 // Fourthly we do not routinely build or test these bindings as part
10455 // of the make && make check cycle, which means that regressions might
10456 // go unnoticed.
10457 //
10458 // Suggestions and patches are welcome.
10459
10460 // To compile:
10461 //
10462 // gmcs Libguestfs.cs
10463 // mono Libguestfs.exe
10464 //
10465 // (You'll probably want to add a Test class / static main function
10466 // otherwise this won't do anything useful).
10467
10468 using System;
10469 using System.IO;
10470 using System.Runtime.InteropServices;
10471 using System.Runtime.Serialization;
10472 using System.Collections;
10473
10474 namespace Guestfs
10475 {
10476   class Error : System.ApplicationException
10477   {
10478     public Error (string message) : base (message) {}
10479     protected Error (SerializationInfo info, StreamingContext context) {}
10480   }
10481
10482   class Guestfs
10483   {
10484     IntPtr _handle;
10485
10486     [DllImport (\"%s\")]
10487     static extern IntPtr guestfs_create ();
10488
10489     public Guestfs ()
10490     {
10491       _handle = guestfs_create ();
10492       if (_handle == IntPtr.Zero)
10493         throw new Error (\"could not create guestfs handle\");
10494     }
10495
10496     [DllImport (\"%s\")]
10497     static extern void guestfs_close (IntPtr h);
10498
10499     ~Guestfs ()
10500     {
10501       guestfs_close (_handle);
10502     }
10503
10504     [DllImport (\"%s\")]
10505     static extern string guestfs_last_error (IntPtr h);
10506
10507 " library library library;
10508
10509   (* Generate C# structure bindings.  We prefix struct names with
10510    * underscore because C# cannot have conflicting struct names and
10511    * method names (eg. "class stat" and "stat").
10512    *)
10513   List.iter (
10514     fun (typ, cols) ->
10515       pr "    [StructLayout (LayoutKind.Sequential)]\n";
10516       pr "    public class _%s {\n" typ;
10517       List.iter (
10518         function
10519         | name, FChar -> pr "      char %s;\n" name
10520         | name, FString -> pr "      string %s;\n" name
10521         | name, FBuffer ->
10522             pr "      uint %s_len;\n" name;
10523             pr "      string %s;\n" name
10524         | name, FUUID ->
10525             pr "      [MarshalAs (UnmanagedType.ByValTStr, SizeConst=16)]\n";
10526             pr "      string %s;\n" name
10527         | name, FUInt32 -> pr "      uint %s;\n" name
10528         | name, FInt32 -> pr "      int %s;\n" name
10529         | name, (FUInt64|FBytes) -> pr "      ulong %s;\n" name
10530         | name, FInt64 -> pr "      long %s;\n" name
10531         | name, FOptPercent -> pr "      float %s; /* [0..100] or -1 */\n" name
10532       ) cols;
10533       pr "    }\n";
10534       pr "\n"
10535   ) structs;
10536
10537   (* Generate C# function bindings. *)
10538   List.iter (
10539     fun (name, style, _, _, _, shortdesc, _) ->
10540       let rec csharp_return_type () =
10541         match fst style with
10542         | RErr -> "void"
10543         | RBool n -> "bool"
10544         | RInt n -> "int"
10545         | RInt64 n -> "long"
10546         | RConstString n
10547         | RConstOptString n
10548         | RString n
10549         | RBufferOut n -> "string"
10550         | RStruct (_,n) -> "_" ^ n
10551         | RHashtable n -> "Hashtable"
10552         | RStringList n -> "string[]"
10553         | RStructList (_,n) -> sprintf "_%s[]" n
10554
10555       and c_return_type () =
10556         match fst style with
10557         | RErr
10558         | RBool _
10559         | RInt _ -> "int"
10560         | RInt64 _ -> "long"
10561         | RConstString _
10562         | RConstOptString _
10563         | RString _
10564         | RBufferOut _ -> "string"
10565         | RStruct (_,n) -> "_" ^ n
10566         | RHashtable _
10567         | RStringList _ -> "string[]"
10568         | RStructList (_,n) -> sprintf "_%s[]" n
10569
10570       and c_error_comparison () =
10571         match fst style with
10572         | RErr
10573         | RBool _
10574         | RInt _
10575         | RInt64 _ -> "== -1"
10576         | RConstString _
10577         | RConstOptString _
10578         | RString _
10579         | RBufferOut _
10580         | RStruct (_,_)
10581         | RHashtable _
10582         | RStringList _
10583         | RStructList (_,_) -> "== null"
10584
10585       and generate_extern_prototype () =
10586         pr "    static extern %s guestfs_%s (IntPtr h"
10587           (c_return_type ()) name;
10588         List.iter (
10589           function
10590           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10591           | FileIn n | FileOut n ->
10592               pr ", [In] string %s" n
10593           | StringList n | DeviceList n ->
10594               pr ", [In] string[] %s" n
10595           | Bool n ->
10596               pr ", bool %s" n
10597           | Int n ->
10598               pr ", int %s" n
10599           | Int64 n ->
10600               pr ", long %s" n
10601         ) (snd style);
10602         pr ");\n"
10603
10604       and generate_public_prototype () =
10605         pr "    public %s %s (" (csharp_return_type ()) name;
10606         let comma = ref false in
10607         let next () =
10608           if !comma then pr ", ";
10609           comma := true
10610         in
10611         List.iter (
10612           function
10613           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10614           | FileIn n | FileOut n ->
10615               next (); pr "string %s" n
10616           | StringList n | DeviceList n ->
10617               next (); pr "string[] %s" n
10618           | Bool n ->
10619               next (); pr "bool %s" n
10620           | Int n ->
10621               next (); pr "int %s" n
10622           | Int64 n ->
10623               next (); pr "long %s" n
10624         ) (snd style);
10625         pr ")\n"
10626
10627       and generate_call () =
10628         pr "guestfs_%s (_handle" name;
10629         List.iter (fun arg -> pr ", %s" (name_of_argt arg)) (snd style);
10630         pr ");\n";
10631       in
10632
10633       pr "    [DllImport (\"%s\")]\n" library;
10634       generate_extern_prototype ();
10635       pr "\n";
10636       pr "    /// <summary>\n";
10637       pr "    /// %s\n" shortdesc;
10638       pr "    /// </summary>\n";
10639       generate_public_prototype ();
10640       pr "    {\n";
10641       pr "      %s r;\n" (c_return_type ());
10642       pr "      r = ";
10643       generate_call ();
10644       pr "      if (r %s)\n" (c_error_comparison ());
10645       pr "        throw new Error (guestfs_last_error (_handle));\n";
10646       (match fst style with
10647        | RErr -> ()
10648        | RBool _ ->
10649            pr "      return r != 0 ? true : false;\n"
10650        | RHashtable _ ->
10651            pr "      Hashtable rr = new Hashtable ();\n";
10652            pr "      for (int i = 0; i < r.Length; i += 2)\n";
10653            pr "        rr.Add (r[i], r[i+1]);\n";
10654            pr "      return rr;\n"
10655        | RInt _ | RInt64 _ | RConstString _ | RConstOptString _
10656        | RString _ | RBufferOut _ | RStruct _ | RStringList _
10657        | RStructList _ ->
10658            pr "      return r;\n"
10659       );
10660       pr "    }\n";
10661       pr "\n";
10662   ) all_functions_sorted;
10663
10664   pr "  }
10665 }
10666 "
10667
10668 and generate_bindtests () =
10669   generate_header CStyle LGPLv2plus;
10670
10671   pr "\
10672 #include <stdio.h>
10673 #include <stdlib.h>
10674 #include <inttypes.h>
10675 #include <string.h>
10676
10677 #include \"guestfs.h\"
10678 #include \"guestfs-internal.h\"
10679 #include \"guestfs-internal-actions.h\"
10680 #include \"guestfs_protocol.h\"
10681
10682 #define error guestfs_error
10683 #define safe_calloc guestfs_safe_calloc
10684 #define safe_malloc guestfs_safe_malloc
10685
10686 static void
10687 print_strings (char *const *argv)
10688 {
10689   int argc;
10690
10691   printf (\"[\");
10692   for (argc = 0; argv[argc] != NULL; ++argc) {
10693     if (argc > 0) printf (\", \");
10694     printf (\"\\\"%%s\\\"\", argv[argc]);
10695   }
10696   printf (\"]\\n\");
10697 }
10698
10699 /* The test0 function prints its parameters to stdout. */
10700 ";
10701
10702   let test0, tests =
10703     match test_functions with
10704     | [] -> assert false
10705     | test0 :: tests -> test0, tests in
10706
10707   let () =
10708     let (name, style, _, _, _, _, _) = test0 in
10709     generate_prototype ~extern:false ~semicolon:false ~newline:true
10710       ~handle:"g" ~prefix:"guestfs__" name style;
10711     pr "{\n";
10712     List.iter (
10713       function
10714       | Pathname n
10715       | Device n | Dev_or_Path n
10716       | String n
10717       | FileIn n
10718       | FileOut n -> pr "  printf (\"%%s\\n\", %s);\n" n
10719       | OptString n -> pr "  printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
10720       | StringList n | DeviceList n -> pr "  print_strings (%s);\n" n
10721       | Bool n -> pr "  printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
10722       | Int n -> pr "  printf (\"%%d\\n\", %s);\n" n
10723       | Int64 n -> pr "  printf (\"%%\" PRIi64 \"\\n\", %s);\n" n
10724     ) (snd style);
10725     pr "  /* Java changes stdout line buffering so we need this: */\n";
10726     pr "  fflush (stdout);\n";
10727     pr "  return 0;\n";
10728     pr "}\n";
10729     pr "\n" in
10730
10731   List.iter (
10732     fun (name, style, _, _, _, _, _) ->
10733       if String.sub name (String.length name - 3) 3 <> "err" then (
10734         pr "/* Test normal return. */\n";
10735         generate_prototype ~extern:false ~semicolon:false ~newline:true
10736           ~handle:"g" ~prefix:"guestfs__" name style;
10737         pr "{\n";
10738         (match fst style with
10739          | RErr ->
10740              pr "  return 0;\n"
10741          | RInt _ ->
10742              pr "  int r;\n";
10743              pr "  sscanf (val, \"%%d\", &r);\n";
10744              pr "  return r;\n"
10745          | RInt64 _ ->
10746              pr "  int64_t r;\n";
10747              pr "  sscanf (val, \"%%\" SCNi64, &r);\n";
10748              pr "  return r;\n"
10749          | RBool _ ->
10750              pr "  return STREQ (val, \"true\");\n"
10751          | RConstString _
10752          | RConstOptString _ ->
10753              (* Can't return the input string here.  Return a static
10754               * string so we ensure we get a segfault if the caller
10755               * tries to free it.
10756               *)
10757              pr "  return \"static string\";\n"
10758          | RString _ ->
10759              pr "  return strdup (val);\n"
10760          | RStringList _ ->
10761              pr "  char **strs;\n";
10762              pr "  int n, i;\n";
10763              pr "  sscanf (val, \"%%d\", &n);\n";
10764              pr "  strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
10765              pr "  for (i = 0; i < n; ++i) {\n";
10766              pr "    strs[i] = safe_malloc (g, 16);\n";
10767              pr "    snprintf (strs[i], 16, \"%%d\", i);\n";
10768              pr "  }\n";
10769              pr "  strs[n] = NULL;\n";
10770              pr "  return strs;\n"
10771          | RStruct (_, typ) ->
10772              pr "  struct guestfs_%s *r;\n" typ;
10773              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
10774              pr "  return r;\n"
10775          | RStructList (_, typ) ->
10776              pr "  struct guestfs_%s_list *r;\n" typ;
10777              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
10778              pr "  sscanf (val, \"%%d\", &r->len);\n";
10779              pr "  r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
10780              pr "  return r;\n"
10781          | RHashtable _ ->
10782              pr "  char **strs;\n";
10783              pr "  int n, i;\n";
10784              pr "  sscanf (val, \"%%d\", &n);\n";
10785              pr "  strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
10786              pr "  for (i = 0; i < n; ++i) {\n";
10787              pr "    strs[i*2] = safe_malloc (g, 16);\n";
10788              pr "    strs[i*2+1] = safe_malloc (g, 16);\n";
10789              pr "    snprintf (strs[i*2], 16, \"%%d\", i);\n";
10790              pr "    snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
10791              pr "  }\n";
10792              pr "  strs[n*2] = NULL;\n";
10793              pr "  return strs;\n"
10794          | RBufferOut _ ->
10795              pr "  return strdup (val);\n"
10796         );
10797         pr "}\n";
10798         pr "\n"
10799       ) else (
10800         pr "/* Test error return. */\n";
10801         generate_prototype ~extern:false ~semicolon:false ~newline:true
10802           ~handle:"g" ~prefix:"guestfs__" name style;
10803         pr "{\n";
10804         pr "  error (g, \"error\");\n";
10805         (match fst style with
10806          | RErr | RInt _ | RInt64 _ | RBool _ ->
10807              pr "  return -1;\n"
10808          | RConstString _ | RConstOptString _
10809          | RString _ | RStringList _ | RStruct _
10810          | RStructList _
10811          | RHashtable _
10812          | RBufferOut _ ->
10813              pr "  return NULL;\n"
10814         );
10815         pr "}\n";
10816         pr "\n"
10817       )
10818   ) tests
10819
10820 and generate_ocaml_bindtests () =
10821   generate_header OCamlStyle GPLv2plus;
10822
10823   pr "\
10824 let () =
10825   let g = Guestfs.create () in
10826 ";
10827
10828   let mkargs args =
10829     String.concat " " (
10830       List.map (
10831         function
10832         | CallString s -> "\"" ^ s ^ "\""
10833         | CallOptString None -> "None"
10834         | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
10835         | CallStringList xs ->
10836             "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
10837         | CallInt i when i >= 0 -> string_of_int i
10838         | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
10839         | CallInt64 i when i >= 0L -> Int64.to_string i ^ "L"
10840         | CallInt64 i (* when i < 0L *) -> "(" ^ Int64.to_string i ^ "L)"
10841         | CallBool b -> string_of_bool b
10842       ) args
10843     )
10844   in
10845
10846   generate_lang_bindtests (
10847     fun f args -> pr "  Guestfs.%s g %s;\n" f (mkargs args)
10848   );
10849
10850   pr "print_endline \"EOF\"\n"
10851
10852 and generate_perl_bindtests () =
10853   pr "#!/usr/bin/perl -w\n";
10854   generate_header HashStyle GPLv2plus;
10855
10856   pr "\
10857 use strict;
10858
10859 use Sys::Guestfs;
10860
10861 my $g = Sys::Guestfs->new ();
10862 ";
10863
10864   let mkargs args =
10865     String.concat ", " (
10866       List.map (
10867         function
10868         | CallString s -> "\"" ^ s ^ "\""
10869         | CallOptString None -> "undef"
10870         | CallOptString (Some s) -> sprintf "\"%s\"" s
10871         | CallStringList xs ->
10872             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10873         | CallInt i -> string_of_int i
10874         | CallInt64 i -> Int64.to_string i
10875         | CallBool b -> if b then "1" else "0"
10876       ) args
10877     )
10878   in
10879
10880   generate_lang_bindtests (
10881     fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
10882   );
10883
10884   pr "print \"EOF\\n\"\n"
10885
10886 and generate_python_bindtests () =
10887   generate_header HashStyle GPLv2plus;
10888
10889   pr "\
10890 import guestfs
10891
10892 g = guestfs.GuestFS ()
10893 ";
10894
10895   let mkargs args =
10896     String.concat ", " (
10897       List.map (
10898         function
10899         | CallString s -> "\"" ^ s ^ "\""
10900         | CallOptString None -> "None"
10901         | CallOptString (Some s) -> sprintf "\"%s\"" s
10902         | CallStringList xs ->
10903             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10904         | CallInt i -> string_of_int i
10905         | CallInt64 i -> Int64.to_string i
10906         | CallBool b -> if b then "1" else "0"
10907       ) args
10908     )
10909   in
10910
10911   generate_lang_bindtests (
10912     fun f args -> pr "g.%s (%s)\n" f (mkargs args)
10913   );
10914
10915   pr "print \"EOF\"\n"
10916
10917 and generate_ruby_bindtests () =
10918   generate_header HashStyle GPLv2plus;
10919
10920   pr "\
10921 require 'guestfs'
10922
10923 g = Guestfs::create()
10924 ";
10925
10926   let mkargs args =
10927     String.concat ", " (
10928       List.map (
10929         function
10930         | CallString s -> "\"" ^ s ^ "\""
10931         | CallOptString None -> "nil"
10932         | CallOptString (Some s) -> sprintf "\"%s\"" s
10933         | CallStringList xs ->
10934             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10935         | CallInt i -> string_of_int i
10936         | CallInt64 i -> Int64.to_string i
10937         | CallBool b -> string_of_bool b
10938       ) args
10939     )
10940   in
10941
10942   generate_lang_bindtests (
10943     fun f args -> pr "g.%s(%s)\n" f (mkargs args)
10944   );
10945
10946   pr "print \"EOF\\n\"\n"
10947
10948 and generate_java_bindtests () =
10949   generate_header CStyle GPLv2plus;
10950
10951   pr "\
10952 import com.redhat.et.libguestfs.*;
10953
10954 public class Bindtests {
10955     public static void main (String[] argv)
10956     {
10957         try {
10958             GuestFS g = new GuestFS ();
10959 ";
10960
10961   let mkargs args =
10962     String.concat ", " (
10963       List.map (
10964         function
10965         | CallString s -> "\"" ^ s ^ "\""
10966         | CallOptString None -> "null"
10967         | CallOptString (Some s) -> sprintf "\"%s\"" s
10968         | CallStringList xs ->
10969             "new String[]{" ^
10970               String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
10971         | CallInt i -> string_of_int i
10972         | CallInt64 i -> Int64.to_string i
10973         | CallBool b -> string_of_bool b
10974       ) args
10975     )
10976   in
10977
10978   generate_lang_bindtests (
10979     fun f args -> pr "            g.%s (%s);\n" f (mkargs args)
10980   );
10981
10982   pr "
10983             System.out.println (\"EOF\");
10984         }
10985         catch (Exception exn) {
10986             System.err.println (exn);
10987             System.exit (1);
10988         }
10989     }
10990 }
10991 "
10992
10993 and generate_haskell_bindtests () =
10994   generate_header HaskellStyle GPLv2plus;
10995
10996   pr "\
10997 module Bindtests where
10998 import qualified Guestfs
10999
11000 main = do
11001   g <- Guestfs.create
11002 ";
11003
11004   let mkargs args =
11005     String.concat " " (
11006       List.map (
11007         function
11008         | CallString s -> "\"" ^ s ^ "\""
11009         | CallOptString None -> "Nothing"
11010         | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
11011         | CallStringList xs ->
11012             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11013         | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
11014         | CallInt i -> string_of_int i
11015         | CallInt64 i when i < 0L -> "(" ^ Int64.to_string i ^ ")"
11016         | CallInt64 i -> Int64.to_string i
11017         | CallBool true -> "True"
11018         | CallBool false -> "False"
11019       ) args
11020     )
11021   in
11022
11023   generate_lang_bindtests (
11024     fun f args -> pr "  Guestfs.%s g %s\n" f (mkargs args)
11025   );
11026
11027   pr "  putStrLn \"EOF\"\n"
11028
11029 (* Language-independent bindings tests - we do it this way to
11030  * ensure there is parity in testing bindings across all languages.
11031  *)
11032 and generate_lang_bindtests call =
11033   call "test0" [CallString "abc"; CallOptString (Some "def");
11034                 CallStringList []; CallBool false;
11035                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11036   call "test0" [CallString "abc"; CallOptString None;
11037                 CallStringList []; CallBool false;
11038                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11039   call "test0" [CallString ""; CallOptString (Some "def");
11040                 CallStringList []; CallBool false;
11041                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11042   call "test0" [CallString ""; CallOptString (Some "");
11043                 CallStringList []; CallBool false;
11044                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11045   call "test0" [CallString "abc"; CallOptString (Some "def");
11046                 CallStringList ["1"]; CallBool false;
11047                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11048   call "test0" [CallString "abc"; CallOptString (Some "def");
11049                 CallStringList ["1"; "2"]; CallBool false;
11050                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11051   call "test0" [CallString "abc"; CallOptString (Some "def");
11052                 CallStringList ["1"]; CallBool true;
11053                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11054   call "test0" [CallString "abc"; CallOptString (Some "def");
11055                 CallStringList ["1"]; CallBool false;
11056                 CallInt (-1); CallInt64 (-1L); CallString "123"; CallString "456"];
11057   call "test0" [CallString "abc"; CallOptString (Some "def");
11058                 CallStringList ["1"]; CallBool false;
11059                 CallInt (-2); CallInt64 (-2L); CallString "123"; CallString "456"];
11060   call "test0" [CallString "abc"; CallOptString (Some "def");
11061                 CallStringList ["1"]; CallBool false;
11062                 CallInt 1; CallInt64 1L; CallString "123"; CallString "456"];
11063   call "test0" [CallString "abc"; CallOptString (Some "def");
11064                 CallStringList ["1"]; CallBool false;
11065                 CallInt 2; CallInt64 2L; CallString "123"; CallString "456"];
11066   call "test0" [CallString "abc"; CallOptString (Some "def");
11067                 CallStringList ["1"]; CallBool false;
11068                 CallInt 4095; CallInt64 4095L; CallString "123"; CallString "456"];
11069   call "test0" [CallString "abc"; CallOptString (Some "def");
11070                 CallStringList ["1"]; CallBool false;
11071                 CallInt 0; CallInt64 0L; CallString ""; CallString ""]
11072
11073 (* XXX Add here tests of the return and error functions. *)
11074
11075 (* Code to generator bindings for virt-inspector.  Currently only
11076  * implemented for OCaml code (for virt-p2v 2.0).
11077  *)
11078 let rng_input = "inspector/virt-inspector.rng"
11079
11080 (* Read the input file and parse it into internal structures.  This is
11081  * by no means a complete RELAX NG parser, but is just enough to be
11082  * able to parse the specific input file.
11083  *)
11084 type rng =
11085   | Element of string * rng list        (* <element name=name/> *)
11086   | Attribute of string * rng list        (* <attribute name=name/> *)
11087   | Interleave of rng list                (* <interleave/> *)
11088   | ZeroOrMore of rng                        (* <zeroOrMore/> *)
11089   | OneOrMore of rng                        (* <oneOrMore/> *)
11090   | Optional of rng                        (* <optional/> *)
11091   | Choice of string list                (* <choice><value/>*</choice> *)
11092   | Value of string                        (* <value>str</value> *)
11093   | Text                                (* <text/> *)
11094
11095 let rec string_of_rng = function
11096   | Element (name, xs) ->
11097       "Element (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11098   | Attribute (name, xs) ->
11099       "Attribute (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11100   | Interleave xs -> "Interleave (" ^ string_of_rng_list xs ^ ")"
11101   | ZeroOrMore rng -> "ZeroOrMore (" ^ string_of_rng rng ^ ")"
11102   | OneOrMore rng -> "OneOrMore (" ^ string_of_rng rng ^ ")"
11103   | Optional rng -> "Optional (" ^ string_of_rng rng ^ ")"
11104   | Choice values -> "Choice [" ^ String.concat ", " values ^ "]"
11105   | Value value -> "Value \"" ^ value ^ "\""
11106   | Text -> "Text"
11107
11108 and string_of_rng_list xs =
11109   String.concat ", " (List.map string_of_rng xs)
11110
11111 let rec parse_rng ?defines context = function
11112   | [] -> []
11113   | Xml.Element ("element", ["name", name], children) :: rest ->
11114       Element (name, parse_rng ?defines context children)
11115       :: parse_rng ?defines context rest
11116   | Xml.Element ("attribute", ["name", name], children) :: rest ->
11117       Attribute (name, parse_rng ?defines context children)
11118       :: parse_rng ?defines context rest
11119   | Xml.Element ("interleave", [], children) :: rest ->
11120       Interleave (parse_rng ?defines context children)
11121       :: parse_rng ?defines context rest
11122   | Xml.Element ("zeroOrMore", [], [child]) :: rest ->
11123       let rng = parse_rng ?defines context [child] in
11124       (match rng with
11125        | [child] -> ZeroOrMore child :: parse_rng ?defines context rest
11126        | _ ->
11127            failwithf "%s: <zeroOrMore> contains more than one child element"
11128              context
11129       )
11130   | Xml.Element ("oneOrMore", [], [child]) :: rest ->
11131       let rng = parse_rng ?defines context [child] in
11132       (match rng with
11133        | [child] -> OneOrMore child :: parse_rng ?defines context rest
11134        | _ ->
11135            failwithf "%s: <oneOrMore> contains more than one child element"
11136              context
11137       )
11138   | Xml.Element ("optional", [], [child]) :: rest ->
11139       let rng = parse_rng ?defines context [child] in
11140       (match rng with
11141        | [child] -> Optional child :: parse_rng ?defines context rest
11142        | _ ->
11143            failwithf "%s: <optional> contains more than one child element"
11144              context
11145       )
11146   | Xml.Element ("choice", [], children) :: rest ->
11147       let values = List.map (
11148         function Xml.Element ("value", [], [Xml.PCData value]) -> value
11149         | _ ->
11150             failwithf "%s: can't handle anything except <value> in <choice>"
11151               context
11152       ) children in
11153       Choice values
11154       :: parse_rng ?defines context rest
11155   | Xml.Element ("value", [], [Xml.PCData value]) :: rest ->
11156       Value value :: parse_rng ?defines context rest
11157   | Xml.Element ("text", [], []) :: rest ->
11158       Text :: parse_rng ?defines context rest
11159   | Xml.Element ("ref", ["name", name], []) :: rest ->
11160       (* Look up the reference.  Because of limitations in this parser,
11161        * we can't handle arbitrarily nested <ref> yet.  You can only
11162        * use <ref> from inside <start>.
11163        *)
11164       (match defines with
11165        | None ->
11166            failwithf "%s: contains <ref>, but no refs are defined yet" context
11167        | Some map ->
11168            let rng = StringMap.find name map in
11169            rng @ parse_rng ?defines context rest
11170       )
11171   | x :: _ ->
11172       failwithf "%s: can't handle '%s' in schema" context (Xml.to_string x)
11173
11174 let grammar =
11175   let xml = Xml.parse_file rng_input in
11176   match xml with
11177   | Xml.Element ("grammar", _,
11178                  Xml.Element ("start", _, gram) :: defines) ->
11179       (* The <define/> elements are referenced in the <start> section,
11180        * so build a map of those first.
11181        *)
11182       let defines = List.fold_left (
11183         fun map ->
11184           function Xml.Element ("define", ["name", name], defn) ->
11185             StringMap.add name defn map
11186           | _ ->
11187               failwithf "%s: expected <define name=name/>" rng_input
11188       ) StringMap.empty defines in
11189       let defines = StringMap.mapi parse_rng defines in
11190
11191       (* Parse the <start> clause, passing the defines. *)
11192       parse_rng ~defines "<start>" gram
11193   | _ ->
11194       failwithf "%s: input is not <grammar><start/><define>*</grammar>"
11195         rng_input
11196
11197 let name_of_field = function
11198   | Element (name, _) | Attribute (name, _)
11199   | ZeroOrMore (Element (name, _))
11200   | OneOrMore (Element (name, _))
11201   | Optional (Element (name, _)) -> name
11202   | Optional (Attribute (name, _)) -> name
11203   | Text -> (* an unnamed field in an element *)
11204       "data"
11205   | rng ->
11206       failwithf "name_of_field failed at: %s" (string_of_rng rng)
11207
11208 (* At the moment this function only generates OCaml types.  However we
11209  * should parameterize it later so it can generate types/structs in a
11210  * variety of languages.
11211  *)
11212 let generate_types xs =
11213   (* A simple type is one that can be printed out directly, eg.
11214    * "string option".  A complex type is one which has a name and has
11215    * to be defined via another toplevel definition, eg. a struct.
11216    *
11217    * generate_type generates code for either simple or complex types.
11218    * In the simple case, it returns the string ("string option").  In
11219    * the complex case, it returns the name ("mountpoint").  In the
11220    * complex case it has to print out the definition before returning,
11221    * so it should only be called when we are at the beginning of a
11222    * new line (BOL context).
11223    *)
11224   let rec generate_type = function
11225     | Text ->                                (* string *)
11226         "string", true
11227     | Choice values ->                        (* [`val1|`val2|...] *)
11228         "[" ^ String.concat "|" (List.map ((^)"`") values) ^ "]", true
11229     | ZeroOrMore rng ->                        (* <rng> list *)
11230         let t, is_simple = generate_type rng in
11231         t ^ " list (* 0 or more *)", is_simple
11232     | OneOrMore rng ->                        (* <rng> list *)
11233         let t, is_simple = generate_type rng in
11234         t ^ " list (* 1 or more *)", is_simple
11235                                         (* virt-inspector hack: bool *)
11236     | Optional (Attribute (name, [Value "1"])) ->
11237         "bool", true
11238     | Optional rng ->                        (* <rng> list *)
11239         let t, is_simple = generate_type rng in
11240         t ^ " option", is_simple
11241                                         (* type name = { fields ... } *)
11242     | Element (name, fields) when is_attrs_interleave fields ->
11243         generate_type_struct name (get_attrs_interleave fields)
11244     | Element (name, [field])                (* type name = field *)
11245     | Attribute (name, [field]) ->
11246         let t, is_simple = generate_type field in
11247         if is_simple then (t, true)
11248         else (
11249           pr "type %s = %s\n" name t;
11250           name, false
11251         )
11252     | Element (name, fields) ->              (* type name = { fields ... } *)
11253         generate_type_struct name fields
11254     | rng ->
11255         failwithf "generate_type failed at: %s" (string_of_rng rng)
11256
11257   and is_attrs_interleave = function
11258     | [Interleave _] -> true
11259     | Attribute _ :: fields -> is_attrs_interleave fields
11260     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11261     | _ -> false
11262
11263   and get_attrs_interleave = function
11264     | [Interleave fields] -> fields
11265     | ((Attribute _) as field) :: fields
11266     | ((Optional (Attribute _)) as field) :: fields ->
11267         field :: get_attrs_interleave fields
11268     | _ -> assert false
11269
11270   and generate_types xs =
11271     List.iter (fun x -> ignore (generate_type x)) xs
11272
11273   and generate_type_struct name fields =
11274     (* Calculate the types of the fields first.  We have to do this
11275      * before printing anything so we are still in BOL context.
11276      *)
11277     let types = List.map fst (List.map generate_type fields) in
11278
11279     (* Special case of a struct containing just a string and another
11280      * field.  Turn it into an assoc list.
11281      *)
11282     match types with
11283     | ["string"; other] ->
11284         let fname1, fname2 =
11285           match fields with
11286           | [f1; f2] -> name_of_field f1, name_of_field f2
11287           | _ -> assert false in
11288         pr "type %s = string * %s (* %s -> %s *)\n" name other fname1 fname2;
11289         name, false
11290
11291     | types ->
11292         pr "type %s = {\n" name;
11293         List.iter (
11294           fun (field, ftype) ->
11295             let fname = name_of_field field in
11296             pr "  %s_%s : %s;\n" name fname ftype
11297         ) (List.combine fields types);
11298         pr "}\n";
11299         (* Return the name of this type, and
11300          * false because it's not a simple type.
11301          *)
11302         name, false
11303   in
11304
11305   generate_types xs
11306
11307 let generate_parsers xs =
11308   (* As for generate_type above, generate_parser makes a parser for
11309    * some type, and returns the name of the parser it has generated.
11310    * Because it (may) need to print something, it should always be
11311    * called in BOL context.
11312    *)
11313   let rec generate_parser = function
11314     | Text ->                                (* string *)
11315         "string_child_or_empty"
11316     | Choice values ->                        (* [`val1|`val2|...] *)
11317         sprintf "(fun x -> match Xml.pcdata (first_child x) with %s | str -> failwith (\"unexpected field value: \" ^ str))"
11318           (String.concat "|"
11319              (List.map (fun v -> sprintf "%S -> `%s" v v) values))
11320     | ZeroOrMore rng ->                        (* <rng> list *)
11321         let pa = generate_parser rng in
11322         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11323     | OneOrMore rng ->                        (* <rng> list *)
11324         let pa = generate_parser rng in
11325         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11326                                         (* virt-inspector hack: bool *)
11327     | Optional (Attribute (name, [Value "1"])) ->
11328         sprintf "(fun x -> try ignore (Xml.attrib x %S); true with Xml.No_attribute _ -> false)" name
11329     | Optional rng ->                        (* <rng> list *)
11330         let pa = generate_parser rng in
11331         sprintf "(function None -> None | Some x -> Some (%s x))" pa
11332                                         (* type name = { fields ... } *)
11333     | Element (name, fields) when is_attrs_interleave fields ->
11334         generate_parser_struct name (get_attrs_interleave fields)
11335     | Element (name, [field]) ->        (* type name = field *)
11336         let pa = generate_parser field in
11337         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11338         pr "let %s =\n" parser_name;
11339         pr "  %s\n" pa;
11340         pr "let parse_%s = %s\n" name parser_name;
11341         parser_name
11342     | Attribute (name, [field]) ->
11343         let pa = generate_parser field in
11344         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11345         pr "let %s =\n" parser_name;
11346         pr "  %s\n" pa;
11347         pr "let parse_%s = %s\n" name parser_name;
11348         parser_name
11349     | Element (name, fields) ->              (* type name = { fields ... } *)
11350         generate_parser_struct name ([], fields)
11351     | rng ->
11352         failwithf "generate_parser failed at: %s" (string_of_rng rng)
11353
11354   and is_attrs_interleave = function
11355     | [Interleave _] -> true
11356     | Attribute _ :: fields -> is_attrs_interleave fields
11357     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11358     | _ -> false
11359
11360   and get_attrs_interleave = function
11361     | [Interleave fields] -> [], fields
11362     | ((Attribute _) as field) :: fields
11363     | ((Optional (Attribute _)) as field) :: fields ->
11364         let attrs, interleaves = get_attrs_interleave fields in
11365         (field :: attrs), interleaves
11366     | _ -> assert false
11367
11368   and generate_parsers xs =
11369     List.iter (fun x -> ignore (generate_parser x)) xs
11370
11371   and generate_parser_struct name (attrs, interleaves) =
11372     (* Generate parsers for the fields first.  We have to do this
11373      * before printing anything so we are still in BOL context.
11374      *)
11375     let fields = attrs @ interleaves in
11376     let pas = List.map generate_parser fields in
11377
11378     (* Generate an intermediate tuple from all the fields first.
11379      * If the type is just a string + another field, then we will
11380      * return this directly, otherwise it is turned into a record.
11381      *
11382      * RELAX NG note: This code treats <interleave> and plain lists of
11383      * fields the same.  In other words, it doesn't bother enforcing
11384      * any ordering of fields in the XML.
11385      *)
11386     pr "let parse_%s x =\n" name;
11387     pr "  let t = (\n    ";
11388     let comma = ref false in
11389     List.iter (
11390       fun x ->
11391         if !comma then pr ",\n    ";
11392         comma := true;
11393         match x with
11394         | Optional (Attribute (fname, [field])), pa ->
11395             pr "%s x" pa
11396         | Optional (Element (fname, [field])), pa ->
11397             pr "%s (optional_child %S x)" pa fname
11398         | Attribute (fname, [Text]), _ ->
11399             pr "attribute %S x" fname
11400         | (ZeroOrMore _ | OneOrMore _), pa ->
11401             pr "%s x" pa
11402         | Text, pa ->
11403             pr "%s x" pa
11404         | (field, pa) ->
11405             let fname = name_of_field field in
11406             pr "%s (child %S x)" pa fname
11407     ) (List.combine fields pas);
11408     pr "\n  ) in\n";
11409
11410     (match fields with
11411      | [Element (_, [Text]) | Attribute (_, [Text]); _] ->
11412          pr "  t\n"
11413
11414      | _ ->
11415          pr "  (Obj.magic t : %s)\n" name
11416 (*
11417          List.iter (
11418            function
11419            | (Optional (Attribute (fname, [field])), pa) ->
11420                pr "  %s_%s =\n" name fname;
11421                pr "    %s x;\n" pa
11422            | (Optional (Element (fname, [field])), pa) ->
11423                pr "  %s_%s =\n" name fname;
11424                pr "    (let x = optional_child %S x in\n" fname;
11425                pr "     %s x);\n" pa
11426            | (field, pa) ->
11427                let fname = name_of_field field in
11428                pr "  %s_%s =\n" name fname;
11429                pr "    (let x = child %S x in\n" fname;
11430                pr "     %s x);\n" pa
11431          ) (List.combine fields pas);
11432          pr "}\n"
11433 *)
11434     );
11435     sprintf "parse_%s" name
11436   in
11437
11438   generate_parsers xs
11439
11440 (* Generate ocaml/guestfs_inspector.mli. *)
11441 let generate_ocaml_inspector_mli () =
11442   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11443
11444   pr "\
11445 (** This is an OCaml language binding to the external [virt-inspector]
11446     program.
11447
11448     For more information, please read the man page [virt-inspector(1)].
11449 *)
11450
11451 ";
11452
11453   generate_types grammar;
11454   pr "(** The nested information returned from the {!inspect} function. *)\n";
11455   pr "\n";
11456
11457   pr "\
11458 val inspect : ?connect:string -> ?xml:string -> string list -> operatingsystems
11459 (** To inspect a libvirt domain called [name], pass a singleton
11460     list: [inspect [name]].  When using libvirt only, you may
11461     optionally pass a libvirt URI using [inspect ~connect:uri ...].
11462
11463     To inspect a disk image or images, pass a list of the filenames
11464     of the disk images: [inspect filenames]
11465
11466     This function inspects the given guest or disk images and
11467     returns a list of operating system(s) found and a large amount
11468     of information about them.  In the vast majority of cases,
11469     a virtual machine only contains a single operating system.
11470
11471     If the optional [~xml] parameter is given, then this function
11472     skips running the external virt-inspector program and just
11473     parses the given XML directly (which is expected to be XML
11474     produced from a previous run of virt-inspector).  The list of
11475     names and connect URI are ignored in this case.
11476
11477     This function can throw a wide variety of exceptions, for example
11478     if the external virt-inspector program cannot be found, or if
11479     it doesn't generate valid XML.
11480 *)
11481 "
11482
11483 (* Generate ocaml/guestfs_inspector.ml. *)
11484 let generate_ocaml_inspector_ml () =
11485   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11486
11487   pr "open Unix\n";
11488   pr "\n";
11489
11490   generate_types grammar;
11491   pr "\n";
11492
11493   pr "\
11494 (* Misc functions which are used by the parser code below. *)
11495 let first_child = function
11496   | Xml.Element (_, _, c::_) -> c
11497   | Xml.Element (name, _, []) ->
11498       failwith (\"expected <\" ^ name ^ \"/> to have a child node\")
11499   | Xml.PCData str ->
11500       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11501
11502 let string_child_or_empty = function
11503   | Xml.Element (_, _, [Xml.PCData s]) -> s
11504   | Xml.Element (_, _, []) -> \"\"
11505   | Xml.Element (x, _, _) ->
11506       failwith (\"expected XML tag with a single PCDATA child, but got \" ^
11507                 x ^ \" instead\")
11508   | Xml.PCData str ->
11509       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11510
11511 let optional_child name xml =
11512   let children = Xml.children xml in
11513   try
11514     Some (List.find (function
11515                      | Xml.Element (n, _, _) when n = name -> true
11516                      | _ -> false) children)
11517   with
11518     Not_found -> None
11519
11520 let child name xml =
11521   match optional_child name xml with
11522   | Some c -> c
11523   | None ->
11524       failwith (\"mandatory field <\" ^ name ^ \"/> missing in XML output\")
11525
11526 let attribute name xml =
11527   try Xml.attrib xml name
11528   with Xml.No_attribute _ ->
11529     failwith (\"mandatory attribute \" ^ name ^ \" missing in XML output\")
11530
11531 ";
11532
11533   generate_parsers grammar;
11534   pr "\n";
11535
11536   pr "\
11537 (* Run external virt-inspector, then use parser to parse the XML. *)
11538 let inspect ?connect ?xml names =
11539   let xml =
11540     match xml with
11541     | None ->
11542         if names = [] then invalid_arg \"inspect: no names given\";
11543         let cmd = [ \"virt-inspector\"; \"--xml\" ] @
11544           (match connect with None -> [] | Some uri -> [ \"--connect\"; uri ]) @
11545           names in
11546         let cmd = List.map Filename.quote cmd in
11547         let cmd = String.concat \" \" cmd in
11548         let chan = open_process_in cmd in
11549         let xml = Xml.parse_in chan in
11550         (match close_process_in chan with
11551          | WEXITED 0 -> ()
11552          | WEXITED _ -> failwith \"external virt-inspector command failed\"
11553          | WSIGNALED i | WSTOPPED i ->
11554              failwith (\"external virt-inspector command died or stopped on sig \" ^
11555                        string_of_int i)
11556         );
11557         xml
11558     | Some doc ->
11559         Xml.parse_string doc in
11560   parse_operatingsystems xml
11561 "
11562
11563 (* This is used to generate the src/MAX_PROC_NR file which
11564  * contains the maximum procedure number, a surrogate for the
11565  * ABI version number.  See src/Makefile.am for the details.
11566  *)
11567 and generate_max_proc_nr () =
11568   let proc_nrs = List.map (
11569     fun (_, _, proc_nr, _, _, _, _) -> proc_nr
11570   ) daemon_functions in
11571
11572   let max_proc_nr = List.fold_left max 0 proc_nrs in
11573
11574   pr "%d\n" max_proc_nr
11575
11576 let output_to filename k =
11577   let filename_new = filename ^ ".new" in
11578   chan := open_out filename_new;
11579   k ();
11580   close_out !chan;
11581   chan := Pervasives.stdout;
11582
11583   (* Is the new file different from the current file? *)
11584   if Sys.file_exists filename && files_equal filename filename_new then
11585     unlink filename_new                 (* same, so skip it *)
11586   else (
11587     (* different, overwrite old one *)
11588     (try chmod filename 0o644 with Unix_error _ -> ());
11589     rename filename_new filename;
11590     chmod filename 0o444;
11591     printf "written %s\n%!" filename;
11592   )
11593
11594 let perror msg = function
11595   | Unix_error (err, _, _) ->
11596       eprintf "%s: %s\n" msg (error_message err)
11597   | exn ->
11598       eprintf "%s: %s\n" msg (Printexc.to_string exn)
11599
11600 (* Main program. *)
11601 let () =
11602   let lock_fd =
11603     try openfile "HACKING" [O_RDWR] 0
11604     with
11605     | Unix_error (ENOENT, _, _) ->
11606         eprintf "\
11607 You are probably running this from the wrong directory.
11608 Run it from the top source directory using the command
11609   src/generator.ml
11610 ";
11611         exit 1
11612     | exn ->
11613         perror "open: HACKING" exn;
11614         exit 1 in
11615
11616   (* Acquire a lock so parallel builds won't try to run the generator
11617    * twice at the same time.  Subsequent builds will wait for the first
11618    * one to finish.  Note the lock is released implicitly when the
11619    * program exits.
11620    *)
11621   (try lockf lock_fd F_LOCK 1
11622    with exn ->
11623      perror "lock: HACKING" exn;
11624      exit 1);
11625
11626   check_functions ();
11627
11628   output_to "src/guestfs_protocol.x" generate_xdr;
11629   output_to "src/guestfs-structs.h" generate_structs_h;
11630   output_to "src/guestfs-actions.h" generate_actions_h;
11631   output_to "src/guestfs-internal-actions.h" generate_internal_actions_h;
11632   output_to "src/guestfs-actions.c" generate_client_actions;
11633   output_to "src/guestfs-bindtests.c" generate_bindtests;
11634   output_to "src/guestfs-structs.pod" generate_structs_pod;
11635   output_to "src/guestfs-actions.pod" generate_actions_pod;
11636   output_to "src/guestfs-availability.pod" generate_availability_pod;
11637   output_to "src/MAX_PROC_NR" generate_max_proc_nr;
11638   output_to "src/libguestfs.syms" generate_linker_script;
11639   output_to "daemon/actions.h" generate_daemon_actions_h;
11640   output_to "daemon/stubs.c" generate_daemon_actions;
11641   output_to "daemon/names.c" generate_daemon_names;
11642   output_to "daemon/optgroups.c" generate_daemon_optgroups_c;
11643   output_to "daemon/optgroups.h" generate_daemon_optgroups_h;
11644   output_to "capitests/tests.c" generate_tests;
11645   output_to "fish/cmds.c" generate_fish_cmds;
11646   output_to "fish/completion.c" generate_fish_completion;
11647   output_to "fish/guestfish-actions.pod" generate_fish_actions_pod;
11648   output_to "ocaml/guestfs.mli" generate_ocaml_mli;
11649   output_to "ocaml/guestfs.ml" generate_ocaml_ml;
11650   output_to "ocaml/guestfs_c_actions.c" generate_ocaml_c;
11651   output_to "ocaml/bindtests.ml" generate_ocaml_bindtests;
11652   output_to "ocaml/guestfs_inspector.mli" generate_ocaml_inspector_mli;
11653   output_to "ocaml/guestfs_inspector.ml" generate_ocaml_inspector_ml;
11654   output_to "perl/Guestfs.xs" generate_perl_xs;
11655   output_to "perl/lib/Sys/Guestfs.pm" generate_perl_pm;
11656   output_to "perl/bindtests.pl" generate_perl_bindtests;
11657   output_to "python/guestfs-py.c" generate_python_c;
11658   output_to "python/guestfs.py" generate_python_py;
11659   output_to "python/bindtests.py" generate_python_bindtests;
11660   output_to "ruby/ext/guestfs/_guestfs.c" generate_ruby_c;
11661   output_to "ruby/bindtests.rb" generate_ruby_bindtests;
11662   output_to "java/com/redhat/et/libguestfs/GuestFS.java" generate_java_java;
11663
11664   List.iter (
11665     fun (typ, jtyp) ->
11666       let cols = cols_of_struct typ in
11667       let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
11668       output_to filename (generate_java_struct jtyp cols);
11669   ) java_structs;
11670
11671   output_to "java/Makefile.inc" generate_java_makefile_inc;
11672   output_to "java/com_redhat_et_libguestfs_GuestFS.c" generate_java_c;
11673   output_to "java/Bindtests.java" generate_java_bindtests;
11674   output_to "haskell/Guestfs.hs" generate_haskell_hs;
11675   output_to "haskell/Bindtests.hs" generate_haskell_bindtests;
11676   output_to "csharp/Libguestfs.cs" generate_csharp;
11677
11678   (* Always generate this file last, and unconditionally.  It's used
11679    * by the Makefile to know when we must re-run the generator.
11680    *)
11681   let chan = open_out "src/stamp-generator" in
11682   fprintf chan "1\n";
11683   close_out chan;
11684
11685   printf "generated %d lines of code\n" !lines