a1d3549ac3a33a5c02b0c391dc4c600395404728
[libguestfs.git] / src / generator.ml
1 #!/usr/bin/env ocaml
2 (* libguestfs
3  * Copyright (C) 2009 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 below), and
25  * daemon/<somefile>.c to write the implementation.
26  *
27  * After editing this file, run it (./src/generator.ml) to regenerate all the
28  * output files.  Note that if you are using a separate build directory you
29  * must run generator.ml from the _source_ directory.
30  *
31  * IMPORTANT: This script should NOT print any warnings.  If it prints
32  * warnings, you should treat them as errors.
33  *)
34
35 #load "unix.cma";;
36 #load "str.cma";;
37
38 open Unix
39 open Printf
40
41 type style = ret * args
42 and ret =
43     (* "RErr" as a return value means an int used as a simple error
44      * indication, ie. 0 or -1.
45      *)
46   | RErr
47
48     (* "RInt" as a return value means an int which is -1 for error
49      * or any value >= 0 on success.  Only use this for smallish
50      * positive ints (0 <= i < 2^30).
51      *)
52   | RInt of string
53
54     (* "RInt64" is the same as RInt, but is guaranteed to be able
55      * to return a full 64 bit value, _except_ that -1 means error
56      * (so -1 cannot be a valid, non-error return value).
57      *)
58   | RInt64 of string
59
60     (* "RBool" is a bool return value which can be true/false or
61      * -1 for error.
62      *)
63   | RBool of string
64
65     (* "RConstString" is a string that refers to a constant value.
66      * The return value must NOT be NULL (since NULL indicates
67      * an error).
68      *
69      * Try to avoid using this.  In particular you cannot use this
70      * for values returned from the daemon, because there is no
71      * thread-safe way to return them in the C API.
72      *)
73   | RConstString of string
74
75     (* "RConstOptString" is an even more broken version of
76      * "RConstString".  The returned string may be NULL and there
77      * is no way to return an error indication.  Avoid using this!
78      *)
79   | RConstOptString of string
80
81     (* "RString" is a returned string.  It must NOT be NULL, since
82      * a NULL return indicates an error.  The caller frees this.
83      *)
84   | RString of string
85
86     (* "RStringList" is a list of strings.  No string in the list
87      * can be NULL.  The caller frees the strings and the array.
88      *)
89   | RStringList of string
90
91     (* "RStruct" is a function which returns a single named structure
92      * or an error indication (in C, a struct, and in other languages
93      * with varying representations, but usually very efficient).  See
94      * after the function list below for the structures.
95      *)
96   | RStruct of string * string          (* name of retval, name of struct *)
97
98     (* "RStructList" is a function which returns either a list/array
99      * of structures (could be zero-length), or an error indication.
100      *)
101   | RStructList of string * string      (* name of retval, name of struct *)
102
103     (* Key-value pairs of untyped strings.  Turns into a hashtable or
104      * dictionary in languages which support it.  DON'T use this as a
105      * general "bucket" for results.  Prefer a stronger typed return
106      * value if one is available, or write a custom struct.  Don't use
107      * this if the list could potentially be very long, since it is
108      * inefficient.  Keys should be unique.  NULLs are not permitted.
109      *)
110   | RHashtable of string
111
112     (* "RBufferOut" is handled almost exactly like RString, but
113      * it allows the string to contain arbitrary 8 bit data including
114      * ASCII NUL.  In the C API this causes an implicit extra parameter
115      * to be added of type <size_t *size_r>.  The extra parameter
116      * returns the actual size of the return buffer in bytes.
117      *
118      * Other programming languages support strings with arbitrary 8 bit
119      * data.
120      *
121      * At the RPC layer we have to use the opaque<> type instead of
122      * string<>.  Returned data is still limited to the max message
123      * size (ie. ~ 2 MB).
124      *)
125   | RBufferOut of string
126
127 and args = argt list    (* Function parameters, guestfs handle is implicit. *)
128
129     (* Note in future we should allow a "variable args" parameter as
130      * the final parameter, to allow commands like
131      *   chmod mode file [file(s)...]
132      * This is not implemented yet, but many commands (such as chmod)
133      * are currently defined with the argument order keeping this future
134      * possibility in mind.
135      *)
136 and argt =
137   | String of string    (* const char *name, cannot be NULL *)
138   | Device of string    (* /dev device name, cannot be NULL *)
139   | Pathname of string  (* file name, cannot be NULL *)
140   | Dev_or_Path of string (* /dev device name or Pathname, cannot be NULL *)
141   | OptString of string (* const char *name, may be NULL *)
142   | StringList of string(* list of strings (each string cannot be NULL) *)
143   | DeviceList of string(* list of Device names (each cannot be NULL) *)
144   | Bool of string      (* boolean *)
145   | Int of string       (* int (smallish ints, signed, <= 31 bits) *)
146   | Int64 of string     (* any 64 bit int *)
147     (* These are treated as filenames (simple string parameters) in
148      * the C API and bindings.  But in the RPC protocol, we transfer
149      * the actual file content up to or down from the daemon.
150      * FileIn: local machine -> daemon (in request)
151      * FileOut: daemon -> local machine (in reply)
152      * In guestfish (only), the special name "-" means read from
153      * stdin or write to stdout.
154      *)
155   | FileIn of string
156   | FileOut of string
157 (* Not implemented:
158     (* Opaque buffer which can contain arbitrary 8 bit data.
159      * In the C API, this is expressed as <char *, int> pair.
160      * Most other languages have a string type which can contain
161      * ASCII NUL.  We use whatever type is appropriate for each
162      * language.
163      * Buffers are limited by the total message size.  To transfer
164      * large blocks of data, use FileIn/FileOut parameters instead.
165      * To return an arbitrary buffer, use RBufferOut.
166      *)
167   | BufferIn of string
168 *)
169
170 type flags =
171   | ProtocolLimitWarning  (* display warning about protocol size limits *)
172   | DangerWillRobinson    (* flags particularly dangerous commands *)
173   | FishAlias of string   (* provide an alias for this cmd in guestfish *)
174   | FishAction of string  (* call this function in guestfish *)
175   | NotInFish             (* do not export via guestfish *)
176   | NotInDocs             (* do not add this function to documentation *)
177   | DeprecatedBy of string (* function is deprecated, use .. instead *)
178
179 (* You can supply zero or as many tests as you want per API call.
180  *
181  * Note that the test environment has 3 block devices, of size 500MB,
182  * 50MB and 10MB (respectively /dev/sda, /dev/sdb, /dev/sdc), and
183  * a fourth ISO block device with some known files on it (/dev/sdd).
184  *
185  * Note for partitioning purposes, the 500MB device has 1015 cylinders.
186  * Number of cylinders was 63 for IDE emulated disks with precisely
187  * the same size.  How exactly this is calculated is a mystery.
188  *
189  * The ISO block device (/dev/sdd) comes from images/test.iso.
190  *
191  * To be able to run the tests in a reasonable amount of time,
192  * the virtual machine and block devices are reused between tests.
193  * So don't try testing kill_subprocess :-x
194  *
195  * Between each test we blockdev-setrw, umount-all, lvm-remove-all.
196  *
197  * Don't assume anything about the previous contents of the block
198  * devices.  Use 'Init*' to create some initial scenarios.
199  *
200  * You can add a prerequisite clause to any individual test.  This
201  * is a run-time check, which, if it fails, causes the test to be
202  * skipped.  Useful if testing a command which might not work on
203  * all variations of libguestfs builds.  A test that has prerequisite
204  * of 'Always' is run unconditionally.
205  *
206  * In addition, packagers can skip individual tests by setting the
207  * environment variables:     eg:
208  *   SKIP_TEST_<CMD>_<NUM>=1  SKIP_TEST_COMMAND_3=1  (skips test #3 of command)
209  *   SKIP_TEST_<CMD>=1        SKIP_TEST_ZEROFREE=1   (skips all zerofree tests)
210  *)
211 type tests = (test_init * test_prereq * test) list
212 and test =
213     (* Run the command sequence and just expect nothing to fail. *)
214   | TestRun of seq
215
216     (* Run the command sequence and expect the output of the final
217      * command to be the string.
218      *)
219   | TestOutput of seq * string
220
221     (* Run the command sequence and expect the output of the final
222      * command to be the list of strings.
223      *)
224   | TestOutputList of seq * string list
225
226     (* Run the command sequence and expect the output of the final
227      * command to be the list of block devices (could be either
228      * "/dev/sd.." or "/dev/hd.." form - we don't check the 5th
229      * character of each string).
230      *)
231   | TestOutputListOfDevices of seq * string list
232
233     (* Run the command sequence and expect the output of the final
234      * command to be the integer.
235      *)
236   | TestOutputInt of seq * int
237
238     (* Run the command sequence and expect the output of the final
239      * command to be <op> <int>, eg. ">=", "1".
240      *)
241   | TestOutputIntOp of seq * string * int
242
243     (* Run the command sequence and expect the output of the final
244      * command to be a true value (!= 0 or != NULL).
245      *)
246   | TestOutputTrue of seq
247
248     (* Run the command sequence and expect the output of the final
249      * command to be a false value (== 0 or == NULL, but not an error).
250      *)
251   | TestOutputFalse of seq
252
253     (* Run the command sequence and expect the output of the final
254      * command to be a list of the given length (but don't care about
255      * content).
256      *)
257   | TestOutputLength of seq * int
258
259     (* Run the command sequence and expect the output of the final
260      * command to be a buffer (RBufferOut), ie. string + size.
261      *)
262   | TestOutputBuffer of seq * string
263
264     (* Run the command sequence and expect the output of the final
265      * command to be a structure.
266      *)
267   | TestOutputStruct of seq * test_field_compare list
268
269     (* Run the command sequence and expect the final command (only)
270      * to fail.
271      *)
272   | TestLastFail of seq
273
274 and test_field_compare =
275   | CompareWithInt of string * int
276   | CompareWithIntOp of string * string * int
277   | CompareWithString of string * string
278   | CompareFieldsIntEq of string * string
279   | CompareFieldsStrEq of string * string
280
281 (* Test prerequisites. *)
282 and test_prereq =
283     (* Test always runs. *)
284   | Always
285
286     (* Test is currently disabled - eg. it fails, or it tests some
287      * unimplemented feature.
288      *)
289   | Disabled
290
291     (* 'string' is some C code (a function body) that should return
292      * true or false.  The test will run if the code returns true.
293      *)
294   | If of string
295
296     (* As for 'If' but the test runs _unless_ the code returns true. *)
297   | Unless of string
298
299 (* Some initial scenarios for testing. *)
300 and test_init =
301     (* Do nothing, block devices could contain random stuff including
302      * LVM PVs, and some filesystems might be mounted.  This is usually
303      * a bad idea.
304      *)
305   | InitNone
306
307     (* Block devices are empty and no filesystems are mounted. *)
308   | InitEmpty
309
310     (* /dev/sda contains a single partition /dev/sda1, with random
311      * content.  /dev/sdb and /dev/sdc may have random content.
312      * No LVM.
313      *)
314   | InitPartition
315
316     (* /dev/sda contains a single partition /dev/sda1, which is formatted
317      * as ext2, empty [except for lost+found] and mounted on /.
318      * /dev/sdb and /dev/sdc may have random content.
319      * No LVM.
320      *)
321   | InitBasicFS
322
323     (* /dev/sda:
324      *   /dev/sda1 (is a PV):
325      *     /dev/VG/LV (size 8MB):
326      *       formatted as ext2, empty [except for lost+found], mounted on /
327      * /dev/sdb and /dev/sdc may have random content.
328      *)
329   | InitBasicFSonLVM
330
331     (* /dev/sdd (the ISO, see images/ directory in source)
332      * is mounted on /
333      *)
334   | InitISOFS
335
336 (* Sequence of commands for testing. *)
337 and seq = cmd list
338 and cmd = string list
339
340 (* Note about long descriptions: When referring to another
341  * action, use the format C<guestfs_other> (ie. the full name of
342  * the C function).  This will be replaced as appropriate in other
343  * language bindings.
344  *
345  * Apart from that, long descriptions are just perldoc paragraphs.
346  *)
347
348 (* Generate a random UUID (used in tests). *)
349 let uuidgen () =
350   let chan = open_process_in "uuidgen" in
351   let uuid = input_line chan in
352   (match close_process_in chan with
353    | WEXITED 0 -> ()
354    | WEXITED _ ->
355        failwith "uuidgen: process exited with non-zero status"
356    | WSIGNALED _ | WSTOPPED _ ->
357        failwith "uuidgen: process signalled or stopped by signal"
358   );
359   uuid
360
361 (* These test functions are used in the language binding tests. *)
362
363 let test_all_args = [
364   String "str";
365   OptString "optstr";
366   StringList "strlist";
367   Bool "b";
368   Int "integer";
369   Int64 "integer64";
370   FileIn "filein";
371   FileOut "fileout";
372 ]
373
374 let test_all_rets = [
375   (* except for RErr, which is tested thoroughly elsewhere *)
376   "test0rint",         RInt "valout";
377   "test0rint64",       RInt64 "valout";
378   "test0rbool",        RBool "valout";
379   "test0rconststring", RConstString "valout";
380   "test0rconstoptstring", RConstOptString "valout";
381   "test0rstring",      RString "valout";
382   "test0rstringlist",  RStringList "valout";
383   "test0rstruct",      RStruct ("valout", "lvm_pv");
384   "test0rstructlist",  RStructList ("valout", "lvm_pv");
385   "test0rhashtable",   RHashtable "valout";
386 ]
387
388 let test_functions = [
389   ("test0", (RErr, test_all_args), -1, [NotInFish; NotInDocs],
390    [],
391    "internal test function - do not use",
392    "\
393 This is an internal test function which is used to test whether
394 the automatically generated bindings can handle every possible
395 parameter type correctly.
396
397 It echos the contents of each parameter to stdout.
398
399 You probably don't want to call this function.");
400 ] @ List.flatten (
401   List.map (
402     fun (name, ret) ->
403       [(name, (ret, [String "val"]), -1, [NotInFish; NotInDocs],
404         [],
405         "internal test function - do not use",
406         "\
407 This is an internal test function which is used to test whether
408 the automatically generated bindings can handle every possible
409 return type correctly.
410
411 It converts string C<val> to the return type.
412
413 You probably don't want to call this function.");
414        (name ^ "err", (ret, []), -1, [NotInFish; NotInDocs],
415         [],
416         "internal test function - do not use",
417         "\
418 This is an internal test function which is used to test whether
419 the automatically generated bindings can handle every possible
420 return type correctly.
421
422 This function always returns an error.
423
424 You probably don't want to call this function.")]
425   ) test_all_rets
426 )
427
428 (* non_daemon_functions are any functions which don't get processed
429  * in the daemon, eg. functions for setting and getting local
430  * configuration values.
431  *)
432
433 let non_daemon_functions = test_functions @ [
434   ("launch", (RErr, []), -1, [FishAlias "run"; FishAction "launch"],
435    [],
436    "launch the qemu subprocess",
437    "\
438 Internally libguestfs is implemented by running a virtual machine
439 using L<qemu(1)>.
440
441 You should call this after configuring the handle
442 (eg. adding drives) but before performing any actions.");
443
444   ("wait_ready", (RErr, []), -1, [NotInFish],
445    [],
446    "wait until the qemu subprocess launches (no op)",
447    "\
448 This function is a no op.
449
450 In versions of the API E<lt> 1.0.71 you had to call this function
451 just after calling C<guestfs_launch> to wait for the launch
452 to complete.  However this is no longer necessary because
453 C<guestfs_launch> now does the waiting.
454
455 If you see any calls to this function in code then you can just
456 remove them, unless you want to retain compatibility with older
457 versions of the API.");
458
459   ("kill_subprocess", (RErr, []), -1, [],
460    [],
461    "kill the qemu subprocess",
462    "\
463 This kills the qemu subprocess.  You should never need to call this.");
464
465   ("add_drive", (RErr, [String "filename"]), -1, [FishAlias "add"],
466    [],
467    "add an image to examine or modify",
468    "\
469 This function adds a virtual machine disk image C<filename> to the
470 guest.  The first time you call this function, the disk appears as IDE
471 disk 0 (C</dev/sda>) in the guest, the second time as C</dev/sdb>, and
472 so on.
473
474 You don't necessarily need to be root when using libguestfs.  However
475 you obviously do need sufficient permissions to access the filename
476 for whatever operations you want to perform (ie. read access if you
477 just want to read the image or write access if you want to modify the
478 image).
479
480 This is equivalent to the qemu parameter
481 C<-drive file=filename,cache=off,if=...>.
482 C<cache=off> is omitted in cases where it is not supported by
483 the underlying filesystem.
484
485 Note that this call checks for the existence of C<filename>.  This
486 stops you from specifying other types of drive which are supported
487 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
488 the general C<guestfs_config> call instead.");
489
490   ("add_cdrom", (RErr, [String "filename"]), -1, [FishAlias "cdrom"],
491    [],
492    "add a CD-ROM disk image to examine",
493    "\
494 This function adds a virtual CD-ROM disk image to the guest.
495
496 This is equivalent to the qemu parameter C<-cdrom filename>.
497
498 Note that this call checks for the existence of C<filename>.  This
499 stops you from specifying other types of drive which are supported
500 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
501 the general C<guestfs_config> call instead.");
502
503   ("add_drive_ro", (RErr, [String "filename"]), -1, [FishAlias "add-ro"],
504    [],
505    "add a drive in snapshot mode (read-only)",
506    "\
507 This adds a drive in snapshot mode, making it effectively
508 read-only.
509
510 Note that writes to the device are allowed, and will be seen for
511 the duration of the guestfs handle, but they are written
512 to a temporary file which is discarded as soon as the guestfs
513 handle is closed.  We don't currently have any method to enable
514 changes to be committed, although qemu can support this.
515
516 This is equivalent to the qemu parameter
517 C<-drive file=filename,snapshot=on,if=...>.
518
519 Note that this call checks for the existence of C<filename>.  This
520 stops you from specifying other types of drive which are supported
521 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
522 the general C<guestfs_config> call instead.");
523
524   ("config", (RErr, [String "qemuparam"; OptString "qemuvalue"]), -1, [],
525    [],
526    "add qemu parameters",
527    "\
528 This can be used to add arbitrary qemu command line parameters
529 of the form C<-param value>.  Actually it's not quite arbitrary - we
530 prevent you from setting some parameters which would interfere with
531 parameters that we use.
532
533 The first character of C<param> string must be a C<-> (dash).
534
535 C<value> can be NULL.");
536
537   ("set_qemu", (RErr, [String "qemu"]), -1, [FishAlias "qemu"],
538    [],
539    "set the qemu binary",
540    "\
541 Set the qemu binary that we will use.
542
543 The default is chosen when the library was compiled by the
544 configure script.
545
546 You can also override this by setting the C<LIBGUESTFS_QEMU>
547 environment variable.
548
549 Setting C<qemu> to C<NULL> restores the default qemu binary.");
550
551   ("get_qemu", (RConstString "qemu", []), -1, [],
552    [InitNone, Always, TestRun (
553       [["get_qemu"]])],
554    "get the qemu binary",
555    "\
556 Return the current qemu binary.
557
558 This is always non-NULL.  If it wasn't set already, then this will
559 return the default qemu binary name.");
560
561   ("set_path", (RErr, [String "searchpath"]), -1, [FishAlias "path"],
562    [],
563    "set the search path",
564    "\
565 Set the path that libguestfs searches for kernel and initrd.img.
566
567 The default is C<$libdir/guestfs> unless overridden by setting
568 C<LIBGUESTFS_PATH> environment variable.
569
570 Setting C<path> to C<NULL> restores the default path.");
571
572   ("get_path", (RConstString "path", []), -1, [],
573    [InitNone, Always, TestRun (
574       [["get_path"]])],
575    "get the search path",
576    "\
577 Return the current search path.
578
579 This is always non-NULL.  If it wasn't set already, then this will
580 return the default path.");
581
582   ("set_append", (RErr, [OptString "append"]), -1, [FishAlias "append"],
583    [],
584    "add options to kernel command line",
585    "\
586 This function is used to add additional options to the
587 guest kernel command line.
588
589 The default is C<NULL> unless overridden by setting
590 C<LIBGUESTFS_APPEND> environment variable.
591
592 Setting C<append> to C<NULL> means I<no> additional options
593 are passed (libguestfs always adds a few of its own).");
594
595   ("get_append", (RConstOptString "append", []), -1, [],
596    (* This cannot be tested with the current framework.  The
597     * function can return NULL in normal operations, which the
598     * test framework interprets as an error.
599     *)
600    [],
601    "get the additional kernel options",
602    "\
603 Return the additional kernel options which are added to the
604 guest kernel command line.
605
606 If C<NULL> then no options are added.");
607
608   ("set_autosync", (RErr, [Bool "autosync"]), -1, [FishAlias "autosync"],
609    [],
610    "set autosync mode",
611    "\
612 If C<autosync> is true, this enables autosync.  Libguestfs will make a
613 best effort attempt to run C<guestfs_umount_all> followed by
614 C<guestfs_sync> when the handle is closed
615 (also if the program exits without closing handles).
616
617 This is disabled by default (except in guestfish where it is
618 enabled by default).");
619
620   ("get_autosync", (RBool "autosync", []), -1, [],
621    [InitNone, Always, TestRun (
622       [["get_autosync"]])],
623    "get autosync mode",
624    "\
625 Get the autosync flag.");
626
627   ("set_verbose", (RErr, [Bool "verbose"]), -1, [FishAlias "verbose"],
628    [],
629    "set verbose mode",
630    "\
631 If C<verbose> is true, this turns on verbose messages (to C<stderr>).
632
633 Verbose messages are disabled unless the environment variable
634 C<LIBGUESTFS_DEBUG> is defined and set to C<1>.");
635
636   ("get_verbose", (RBool "verbose", []), -1, [],
637    [],
638    "get verbose mode",
639    "\
640 This returns the verbose messages flag.");
641
642   ("is_ready", (RBool "ready", []), -1, [],
643    [InitNone, Always, TestOutputTrue (
644       [["is_ready"]])],
645    "is ready to accept commands",
646    "\
647 This returns true iff this handle is ready to accept commands
648 (in the C<READY> state).
649
650 For more information on states, see L<guestfs(3)>.");
651
652   ("is_config", (RBool "config", []), -1, [],
653    [InitNone, Always, TestOutputFalse (
654       [["is_config"]])],
655    "is in configuration state",
656    "\
657 This returns true iff this handle is being configured
658 (in the C<CONFIG> state).
659
660 For more information on states, see L<guestfs(3)>.");
661
662   ("is_launching", (RBool "launching", []), -1, [],
663    [InitNone, Always, TestOutputFalse (
664       [["is_launching"]])],
665    "is launching subprocess",
666    "\
667 This returns true iff this handle is launching the subprocess
668 (in the C<LAUNCHING> state).
669
670 For more information on states, see L<guestfs(3)>.");
671
672   ("is_busy", (RBool "busy", []), -1, [],
673    [InitNone, Always, TestOutputFalse (
674       [["is_busy"]])],
675    "is busy processing a command",
676    "\
677 This returns true iff this handle is busy processing a command
678 (in the C<BUSY> state).
679
680 For more information on states, see L<guestfs(3)>.");
681
682   ("get_state", (RInt "state", []), -1, [],
683    [],
684    "get the current state",
685    "\
686 This returns the current state as an opaque integer.  This is
687 only useful for printing debug and internal error messages.
688
689 For more information on states, see L<guestfs(3)>.");
690
691   ("set_memsize", (RErr, [Int "memsize"]), -1, [FishAlias "memsize"],
692    [InitNone, Always, TestOutputInt (
693       [["set_memsize"; "500"];
694        ["get_memsize"]], 500)],
695    "set memory allocated to the qemu subprocess",
696    "\
697 This sets the memory size in megabytes allocated to the
698 qemu subprocess.  This only has any effect if called before
699 C<guestfs_launch>.
700
701 You can also change this by setting the environment
702 variable C<LIBGUESTFS_MEMSIZE> before the handle is
703 created.
704
705 For more information on the architecture of libguestfs,
706 see L<guestfs(3)>.");
707
708   ("get_memsize", (RInt "memsize", []), -1, [],
709    [InitNone, Always, TestOutputIntOp (
710       [["get_memsize"]], ">=", 256)],
711    "get memory allocated to the qemu subprocess",
712    "\
713 This gets the memory size in megabytes allocated to the
714 qemu subprocess.
715
716 If C<guestfs_set_memsize> was not called
717 on this handle, and if C<LIBGUESTFS_MEMSIZE> was not set,
718 then this returns the compiled-in default value for memsize.
719
720 For more information on the architecture of libguestfs,
721 see L<guestfs(3)>.");
722
723   ("get_pid", (RInt "pid", []), -1, [FishAlias "pid"],
724    [InitNone, Always, TestOutputIntOp (
725       [["get_pid"]], ">=", 1)],
726    "get PID of qemu subprocess",
727    "\
728 Return the process ID of the qemu subprocess.  If there is no
729 qemu subprocess, then this will return an error.
730
731 This is an internal call used for debugging and testing.");
732
733   ("version", (RStruct ("version", "version"), []), -1, [],
734    [InitNone, Always, TestOutputStruct (
735       [["version"]], [CompareWithInt ("major", 1)])],
736    "get the library version number",
737    "\
738 Return the libguestfs version number that the program is linked
739 against.
740
741 Note that because of dynamic linking this is not necessarily
742 the version of libguestfs that you compiled against.  You can
743 compile the program, and then at runtime dynamically link
744 against a completely different C<libguestfs.so> library.
745
746 This call was added in version C<1.0.58>.  In previous
747 versions of libguestfs there was no way to get the version
748 number.  From C code you can use ELF weak linking tricks to find out if
749 this symbol exists (if it doesn't, then it's an earlier version).
750
751 The call returns a structure with four elements.  The first
752 three (C<major>, C<minor> and C<release>) are numbers and
753 correspond to the usual version triplet.  The fourth element
754 (C<extra>) is a string and is normally empty, but may be
755 used for distro-specific information.
756
757 To construct the original version string:
758 C<$major.$minor.$release$extra>
759
760 I<Note:> Don't use this call to test for availability
761 of features.  Distro backports makes this unreliable.");
762
763   ("set_selinux", (RErr, [Bool "selinux"]), -1, [FishAlias "selinux"],
764    [InitNone, Always, TestOutputTrue (
765       [["set_selinux"; "true"];
766        ["get_selinux"]])],
767    "set SELinux enabled or disabled at appliance boot",
768    "\
769 This sets the selinux flag that is passed to the appliance
770 at boot time.  The default is C<selinux=0> (disabled).
771
772 Note that if SELinux is enabled, it is always in
773 Permissive mode (C<enforcing=0>).
774
775 For more information on the architecture of libguestfs,
776 see L<guestfs(3)>.");
777
778   ("get_selinux", (RBool "selinux", []), -1, [],
779    [],
780    "get SELinux enabled flag",
781    "\
782 This returns the current setting of the selinux flag which
783 is passed to the appliance at boot time.  See C<guestfs_set_selinux>.
784
785 For more information on the architecture of libguestfs,
786 see L<guestfs(3)>.");
787
788   ("set_trace", (RErr, [Bool "trace"]), -1, [FishAlias "trace"],
789    [InitNone, Always, TestOutputFalse (
790       [["set_trace"; "false"];
791        ["get_trace"]])],
792    "enable or disable command traces",
793    "\
794 If the command trace flag is set to 1, then commands are
795 printed on stdout before they are executed in a format
796 which is very similar to the one used by guestfish.  In
797 other words, you can run a program with this enabled, and
798 you will get out a script which you can feed to guestfish
799 to perform the same set of actions.
800
801 If you want to trace C API calls into libguestfs (and
802 other libraries) then possibly a better way is to use
803 the external ltrace(1) command.
804
805 Command traces are disabled unless the environment variable
806 C<LIBGUESTFS_TRACE> is defined and set to C<1>.");
807
808   ("get_trace", (RBool "trace", []), -1, [],
809    [],
810    "get command trace enabled flag",
811    "\
812 Return the command trace flag.");
813
814   ("set_direct", (RErr, [Bool "direct"]), -1, [FishAlias "direct"],
815    [InitNone, Always, TestOutputFalse (
816       [["set_direct"; "false"];
817        ["get_direct"]])],
818    "enable or disable direct appliance mode",
819    "\
820 If the direct appliance mode flag is enabled, then stdin and
821 stdout are passed directly through to the appliance once it
822 is launched.
823
824 One consequence of this is that log messages aren't caught
825 by the library and handled by C<guestfs_set_log_message_callback>,
826 but go straight to stdout.
827
828 You probably don't want to use this unless you know what you
829 are doing.
830
831 The default is disabled.");
832
833   ("get_direct", (RBool "direct", []), -1, [],
834    [],
835    "get direct appliance mode flag",
836    "\
837 Return the direct appliance mode flag.");
838
839   ("set_recovery_proc", (RErr, [Bool "recoveryproc"]), -1, [FishAlias "recovery-proc"],
840    [InitNone, Always, TestOutputTrue (
841       [["set_recovery_proc"; "true"];
842        ["get_recovery_proc"]])],
843    "enable or disable the recovery process",
844    "\
845 If this is called with the parameter C<false> then
846 C<guestfs_launch> does not create a recovery process.  The
847 purpose of the recovery process is to stop runaway qemu
848 processes in the case where the main program aborts abruptly.
849
850 This only has any effect if called before C<guestfs_launch>,
851 and the default is true.
852
853 About the only time when you would want to disable this is
854 if the main process will fork itself into the background
855 (\"daemonize\" itself).  In this case the recovery process
856 thinks that the main program has disappeared and so kills
857 qemu, which is not very helpful.");
858
859   ("get_recovery_proc", (RBool "recoveryproc", []), -1, [],
860    [],
861    "get recovery process enabled flag",
862    "\
863 Return the recovery process enabled flag.");
864
865 ]
866
867 (* daemon_functions are any functions which cause some action
868  * to take place in the daemon.
869  *)
870
871 let daemon_functions = [
872   ("mount", (RErr, [Device "device"; String "mountpoint"]), 1, [],
873    [InitEmpty, Always, TestOutput (
874       [["part_disk"; "/dev/sda"; "mbr"];
875        ["mkfs"; "ext2"; "/dev/sda1"];
876        ["mount"; "/dev/sda1"; "/"];
877        ["write_file"; "/new"; "new file contents"; "0"];
878        ["cat"; "/new"]], "new file contents")],
879    "mount a guest disk at a position in the filesystem",
880    "\
881 Mount a guest disk at a position in the filesystem.  Block devices
882 are named C</dev/sda>, C</dev/sdb> and so on, as they were added to
883 the guest.  If those block devices contain partitions, they will have
884 the usual names (eg. C</dev/sda1>).  Also LVM C</dev/VG/LV>-style
885 names can be used.
886
887 The rules are the same as for L<mount(2)>:  A filesystem must
888 first be mounted on C</> before others can be mounted.  Other
889 filesystems can only be mounted on directories which already
890 exist.
891
892 The mounted filesystem is writable, if we have sufficient permissions
893 on the underlying device.
894
895 The filesystem options C<sync> and C<noatime> are set with this
896 call, in order to improve reliability.");
897
898   ("sync", (RErr, []), 2, [],
899    [ InitEmpty, Always, TestRun [["sync"]]],
900    "sync disks, writes are flushed through to the disk image",
901    "\
902 This syncs the disk, so that any writes are flushed through to the
903 underlying disk image.
904
905 You should always call this if you have modified a disk image, before
906 closing the handle.");
907
908   ("touch", (RErr, [Pathname "path"]), 3, [],
909    [InitBasicFS, Always, TestOutputTrue (
910       [["touch"; "/new"];
911        ["exists"; "/new"]])],
912    "update file timestamps or create a new file",
913    "\
914 Touch acts like the L<touch(1)> command.  It can be used to
915 update the timestamps on a file, or, if the file does not exist,
916 to create a new zero-length file.");
917
918   ("cat", (RString "content", [Pathname "path"]), 4, [ProtocolLimitWarning],
919    [InitISOFS, Always, TestOutput (
920       [["cat"; "/known-2"]], "abcdef\n")],
921    "list the contents of a file",
922    "\
923 Return the contents of the file named C<path>.
924
925 Note that this function cannot correctly handle binary files
926 (specifically, files containing C<\\0> character which is treated
927 as end of string).  For those you need to use the C<guestfs_read_file>
928 or C<guestfs_download> functions which have a more complex interface.");
929
930   ("ll", (RString "listing", [Pathname "directory"]), 5, [],
931    [], (* XXX Tricky to test because it depends on the exact format
932         * of the 'ls -l' command, which changes between F10 and F11.
933         *)
934    "list the files in a directory (long format)",
935    "\
936 List the files in C<directory> (relative to the root directory,
937 there is no cwd) in the format of 'ls -la'.
938
939 This command is mostly useful for interactive sessions.  It
940 is I<not> intended that you try to parse the output string.");
941
942   ("ls", (RStringList "listing", [Pathname "directory"]), 6, [],
943    [InitBasicFS, Always, TestOutputList (
944       [["touch"; "/new"];
945        ["touch"; "/newer"];
946        ["touch"; "/newest"];
947        ["ls"; "/"]], ["lost+found"; "new"; "newer"; "newest"])],
948    "list the files in a directory",
949    "\
950 List the files in C<directory> (relative to the root directory,
951 there is no cwd).  The '.' and '..' entries are not returned, but
952 hidden files are shown.
953
954 This command is mostly useful for interactive sessions.  Programs
955 should probably use C<guestfs_readdir> instead.");
956
957   ("list_devices", (RStringList "devices", []), 7, [],
958    [InitEmpty, Always, TestOutputListOfDevices (
959       [["list_devices"]], ["/dev/sda"; "/dev/sdb"; "/dev/sdc"; "/dev/sdd"])],
960    "list the block devices",
961    "\
962 List all the block devices.
963
964 The full block device names are returned, eg. C</dev/sda>");
965
966   ("list_partitions", (RStringList "partitions", []), 8, [],
967    [InitBasicFS, Always, TestOutputListOfDevices (
968       [["list_partitions"]], ["/dev/sda1"]);
969     InitEmpty, Always, TestOutputListOfDevices (
970       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
971        ["list_partitions"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
972    "list the partitions",
973    "\
974 List all the partitions detected on all block devices.
975
976 The full partition device names are returned, eg. C</dev/sda1>
977
978 This does not return logical volumes.  For that you will need to
979 call C<guestfs_lvs>.");
980
981   ("pvs", (RStringList "physvols", []), 9, [],
982    [InitBasicFSonLVM, Always, TestOutputListOfDevices (
983       [["pvs"]], ["/dev/sda1"]);
984     InitEmpty, Always, TestOutputListOfDevices (
985       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
986        ["pvcreate"; "/dev/sda1"];
987        ["pvcreate"; "/dev/sda2"];
988        ["pvcreate"; "/dev/sda3"];
989        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
990    "list the LVM physical volumes (PVs)",
991    "\
992 List all the physical volumes detected.  This is the equivalent
993 of the L<pvs(8)> command.
994
995 This returns a list of just the device names that contain
996 PVs (eg. C</dev/sda2>).
997
998 See also C<guestfs_pvs_full>.");
999
1000   ("vgs", (RStringList "volgroups", []), 10, [],
1001    [InitBasicFSonLVM, Always, TestOutputList (
1002       [["vgs"]], ["VG"]);
1003     InitEmpty, Always, TestOutputList (
1004       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1005        ["pvcreate"; "/dev/sda1"];
1006        ["pvcreate"; "/dev/sda2"];
1007        ["pvcreate"; "/dev/sda3"];
1008        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1009        ["vgcreate"; "VG2"; "/dev/sda3"];
1010        ["vgs"]], ["VG1"; "VG2"])],
1011    "list the LVM volume groups (VGs)",
1012    "\
1013 List all the volumes groups detected.  This is the equivalent
1014 of the L<vgs(8)> command.
1015
1016 This returns a list of just the volume group names that were
1017 detected (eg. C<VolGroup00>).
1018
1019 See also C<guestfs_vgs_full>.");
1020
1021   ("lvs", (RStringList "logvols", []), 11, [],
1022    [InitBasicFSonLVM, Always, TestOutputList (
1023       [["lvs"]], ["/dev/VG/LV"]);
1024     InitEmpty, Always, TestOutputList (
1025       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1026        ["pvcreate"; "/dev/sda1"];
1027        ["pvcreate"; "/dev/sda2"];
1028        ["pvcreate"; "/dev/sda3"];
1029        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1030        ["vgcreate"; "VG2"; "/dev/sda3"];
1031        ["lvcreate"; "LV1"; "VG1"; "50"];
1032        ["lvcreate"; "LV2"; "VG1"; "50"];
1033        ["lvcreate"; "LV3"; "VG2"; "50"];
1034        ["lvs"]], ["/dev/VG1/LV1"; "/dev/VG1/LV2"; "/dev/VG2/LV3"])],
1035    "list the LVM logical volumes (LVs)",
1036    "\
1037 List all the logical volumes detected.  This is the equivalent
1038 of the L<lvs(8)> command.
1039
1040 This returns a list of the logical volume device names
1041 (eg. C</dev/VolGroup00/LogVol00>).
1042
1043 See also C<guestfs_lvs_full>.");
1044
1045   ("pvs_full", (RStructList ("physvols", "lvm_pv"), []), 12, [],
1046    [], (* XXX how to test? *)
1047    "list the LVM physical volumes (PVs)",
1048    "\
1049 List all the physical volumes detected.  This is the equivalent
1050 of the L<pvs(8)> command.  The \"full\" version includes all fields.");
1051
1052   ("vgs_full", (RStructList ("volgroups", "lvm_vg"), []), 13, [],
1053    [], (* XXX how to test? *)
1054    "list the LVM volume groups (VGs)",
1055    "\
1056 List all the volumes groups detected.  This is the equivalent
1057 of the L<vgs(8)> command.  The \"full\" version includes all fields.");
1058
1059   ("lvs_full", (RStructList ("logvols", "lvm_lv"), []), 14, [],
1060    [], (* XXX how to test? *)
1061    "list the LVM logical volumes (LVs)",
1062    "\
1063 List all the logical volumes detected.  This is the equivalent
1064 of the L<lvs(8)> command.  The \"full\" version includes all fields.");
1065
1066   ("read_lines", (RStringList "lines", [Pathname "path"]), 15, [],
1067    [InitISOFS, Always, TestOutputList (
1068       [["read_lines"; "/known-4"]], ["abc"; "def"; "ghi"]);
1069     InitISOFS, Always, TestOutputList (
1070       [["read_lines"; "/empty"]], [])],
1071    "read file as lines",
1072    "\
1073 Return the contents of the file named C<path>.
1074
1075 The file contents are returned as a list of lines.  Trailing
1076 C<LF> and C<CRLF> character sequences are I<not> returned.
1077
1078 Note that this function cannot correctly handle binary files
1079 (specifically, files containing C<\\0> character which is treated
1080 as end of line).  For those you need to use the C<guestfs_read_file>
1081 function which has a more complex interface.");
1082
1083   ("aug_init", (RErr, [Pathname "root"; Int "flags"]), 16, [],
1084    [], (* XXX Augeas code needs tests. *)
1085    "create a new Augeas handle",
1086    "\
1087 Create a new Augeas handle for editing configuration files.
1088 If there was any previous Augeas handle associated with this
1089 guestfs session, then it is closed.
1090
1091 You must call this before using any other C<guestfs_aug_*>
1092 commands.
1093
1094 C<root> is the filesystem root.  C<root> must not be NULL,
1095 use C</> instead.
1096
1097 The flags are the same as the flags defined in
1098 E<lt>augeas.hE<gt>, the logical I<or> of the following
1099 integers:
1100
1101 =over 4
1102
1103 =item C<AUG_SAVE_BACKUP> = 1
1104
1105 Keep the original file with a C<.augsave> extension.
1106
1107 =item C<AUG_SAVE_NEWFILE> = 2
1108
1109 Save changes into a file with extension C<.augnew>, and
1110 do not overwrite original.  Overrides C<AUG_SAVE_BACKUP>.
1111
1112 =item C<AUG_TYPE_CHECK> = 4
1113
1114 Typecheck lenses (can be expensive).
1115
1116 =item C<AUG_NO_STDINC> = 8
1117
1118 Do not use standard load path for modules.
1119
1120 =item C<AUG_SAVE_NOOP> = 16
1121
1122 Make save a no-op, just record what would have been changed.
1123
1124 =item C<AUG_NO_LOAD> = 32
1125
1126 Do not load the tree in C<guestfs_aug_init>.
1127
1128 =back
1129
1130 To close the handle, you can call C<guestfs_aug_close>.
1131
1132 To find out more about Augeas, see L<http://augeas.net/>.");
1133
1134   ("aug_close", (RErr, []), 26, [],
1135    [], (* XXX Augeas code needs tests. *)
1136    "close the current Augeas handle",
1137    "\
1138 Close the current Augeas handle and free up any resources
1139 used by it.  After calling this, you have to call
1140 C<guestfs_aug_init> again before you can use any other
1141 Augeas functions.");
1142
1143   ("aug_defvar", (RInt "nrnodes", [String "name"; OptString "expr"]), 17, [],
1144    [], (* XXX Augeas code needs tests. *)
1145    "define an Augeas variable",
1146    "\
1147 Defines an Augeas variable C<name> whose value is the result
1148 of evaluating C<expr>.  If C<expr> is NULL, then C<name> is
1149 undefined.
1150
1151 On success this returns the number of nodes in C<expr>, or
1152 C<0> if C<expr> evaluates to something which is not a nodeset.");
1153
1154   ("aug_defnode", (RStruct ("nrnodescreated", "int_bool"), [String "name"; String "expr"; String "val"]), 18, [],
1155    [], (* XXX Augeas code needs tests. *)
1156    "define an Augeas node",
1157    "\
1158 Defines a variable C<name> whose value is the result of
1159 evaluating C<expr>.
1160
1161 If C<expr> evaluates to an empty nodeset, a node is created,
1162 equivalent to calling C<guestfs_aug_set> C<expr>, C<value>.
1163 C<name> will be the nodeset containing that single node.
1164
1165 On success this returns a pair containing the
1166 number of nodes in the nodeset, and a boolean flag
1167 if a node was created.");
1168
1169   ("aug_get", (RString "val", [String "augpath"]), 19, [],
1170    [], (* XXX Augeas code needs tests. *)
1171    "look up the value of an Augeas path",
1172    "\
1173 Look up the value associated with C<path>.  If C<path>
1174 matches exactly one node, the C<value> is returned.");
1175
1176   ("aug_set", (RErr, [String "augpath"; String "val"]), 20, [],
1177    [], (* XXX Augeas code needs tests. *)
1178    "set Augeas path to value",
1179    "\
1180 Set the value associated with C<path> to C<value>.");
1181
1182   ("aug_insert", (RErr, [String "augpath"; String "label"; Bool "before"]), 21, [],
1183    [], (* XXX Augeas code needs tests. *)
1184    "insert a sibling Augeas node",
1185    "\
1186 Create a new sibling C<label> for C<path>, inserting it into
1187 the tree before or after C<path> (depending on the boolean
1188 flag C<before>).
1189
1190 C<path> must match exactly one existing node in the tree, and
1191 C<label> must be a label, ie. not contain C</>, C<*> or end
1192 with a bracketed index C<[N]>.");
1193
1194   ("aug_rm", (RInt "nrnodes", [String "augpath"]), 22, [],
1195    [], (* XXX Augeas code needs tests. *)
1196    "remove an Augeas path",
1197    "\
1198 Remove C<path> and all of its children.
1199
1200 On success this returns the number of entries which were removed.");
1201
1202   ("aug_mv", (RErr, [String "src"; String "dest"]), 23, [],
1203    [], (* XXX Augeas code needs tests. *)
1204    "move Augeas node",
1205    "\
1206 Move the node C<src> to C<dest>.  C<src> must match exactly
1207 one node.  C<dest> is overwritten if it exists.");
1208
1209   ("aug_match", (RStringList "matches", [String "augpath"]), 24, [],
1210    [], (* XXX Augeas code needs tests. *)
1211    "return Augeas nodes which match augpath",
1212    "\
1213 Returns a list of paths which match the path expression C<path>.
1214 The returned paths are sufficiently qualified so that they match
1215 exactly one node in the current tree.");
1216
1217   ("aug_save", (RErr, []), 25, [],
1218    [], (* XXX Augeas code needs tests. *)
1219    "write all pending Augeas changes to disk",
1220    "\
1221 This writes all pending changes to disk.
1222
1223 The flags which were passed to C<guestfs_aug_init> affect exactly
1224 how files are saved.");
1225
1226   ("aug_load", (RErr, []), 27, [],
1227    [], (* XXX Augeas code needs tests. *)
1228    "load files into the tree",
1229    "\
1230 Load files into the tree.
1231
1232 See C<aug_load> in the Augeas documentation for the full gory
1233 details.");
1234
1235   ("aug_ls", (RStringList "matches", [String "augpath"]), 28, [],
1236    [], (* XXX Augeas code needs tests. *)
1237    "list Augeas nodes under augpath",
1238    "\
1239 This is just a shortcut for listing C<guestfs_aug_match>
1240 C<path/*> and sorting the resulting nodes into alphabetical order.");
1241
1242   ("rm", (RErr, [Pathname "path"]), 29, [],
1243    [InitBasicFS, Always, TestRun
1244       [["touch"; "/new"];
1245        ["rm"; "/new"]];
1246     InitBasicFS, Always, TestLastFail
1247       [["rm"; "/new"]];
1248     InitBasicFS, Always, TestLastFail
1249       [["mkdir"; "/new"];
1250        ["rm"; "/new"]]],
1251    "remove a file",
1252    "\
1253 Remove the single file C<path>.");
1254
1255   ("rmdir", (RErr, [Pathname "path"]), 30, [],
1256    [InitBasicFS, Always, TestRun
1257       [["mkdir"; "/new"];
1258        ["rmdir"; "/new"]];
1259     InitBasicFS, Always, TestLastFail
1260       [["rmdir"; "/new"]];
1261     InitBasicFS, Always, TestLastFail
1262       [["touch"; "/new"];
1263        ["rmdir"; "/new"]]],
1264    "remove a directory",
1265    "\
1266 Remove the single directory C<path>.");
1267
1268   ("rm_rf", (RErr, [Pathname "path"]), 31, [],
1269    [InitBasicFS, Always, TestOutputFalse
1270       [["mkdir"; "/new"];
1271        ["mkdir"; "/new/foo"];
1272        ["touch"; "/new/foo/bar"];
1273        ["rm_rf"; "/new"];
1274        ["exists"; "/new"]]],
1275    "remove a file or directory recursively",
1276    "\
1277 Remove the file or directory C<path>, recursively removing the
1278 contents if its a directory.  This is like the C<rm -rf> shell
1279 command.");
1280
1281   ("mkdir", (RErr, [Pathname "path"]), 32, [],
1282    [InitBasicFS, Always, TestOutputTrue
1283       [["mkdir"; "/new"];
1284        ["is_dir"; "/new"]];
1285     InitBasicFS, Always, TestLastFail
1286       [["mkdir"; "/new/foo/bar"]]],
1287    "create a directory",
1288    "\
1289 Create a directory named C<path>.");
1290
1291   ("mkdir_p", (RErr, [Pathname "path"]), 33, [],
1292    [InitBasicFS, Always, TestOutputTrue
1293       [["mkdir_p"; "/new/foo/bar"];
1294        ["is_dir"; "/new/foo/bar"]];
1295     InitBasicFS, Always, TestOutputTrue
1296       [["mkdir_p"; "/new/foo/bar"];
1297        ["is_dir"; "/new/foo"]];
1298     InitBasicFS, Always, TestOutputTrue
1299       [["mkdir_p"; "/new/foo/bar"];
1300        ["is_dir"; "/new"]];
1301     (* Regression tests for RHBZ#503133: *)
1302     InitBasicFS, Always, TestRun
1303       [["mkdir"; "/new"];
1304        ["mkdir_p"; "/new"]];
1305     InitBasicFS, Always, TestLastFail
1306       [["touch"; "/new"];
1307        ["mkdir_p"; "/new"]]],
1308    "create a directory and parents",
1309    "\
1310 Create a directory named C<path>, creating any parent directories
1311 as necessary.  This is like the C<mkdir -p> shell command.");
1312
1313   ("chmod", (RErr, [Int "mode"; Pathname "path"]), 34, [],
1314    [], (* XXX Need stat command to test *)
1315    "change file mode",
1316    "\
1317 Change the mode (permissions) of C<path> to C<mode>.  Only
1318 numeric modes are supported.");
1319
1320   ("chown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 35, [],
1321    [], (* XXX Need stat command to test *)
1322    "change file owner and group",
1323    "\
1324 Change the file owner to C<owner> and group to C<group>.
1325
1326 Only numeric uid and gid are supported.  If you want to use
1327 names, you will need to locate and parse the password file
1328 yourself (Augeas support makes this relatively easy).");
1329
1330   ("exists", (RBool "existsflag", [Pathname "path"]), 36, [],
1331    [InitISOFS, Always, TestOutputTrue (
1332       [["exists"; "/empty"]]);
1333     InitISOFS, Always, TestOutputTrue (
1334       [["exists"; "/directory"]])],
1335    "test if file or directory exists",
1336    "\
1337 This returns C<true> if and only if there is a file, directory
1338 (or anything) with the given C<path> name.
1339
1340 See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>.");
1341
1342   ("is_file", (RBool "fileflag", [Pathname "path"]), 37, [],
1343    [InitISOFS, Always, TestOutputTrue (
1344       [["is_file"; "/known-1"]]);
1345     InitISOFS, Always, TestOutputFalse (
1346       [["is_file"; "/directory"]])],
1347    "test if file exists",
1348    "\
1349 This returns C<true> if and only if there is a file
1350 with the given C<path> name.  Note that it returns false for
1351 other objects like directories.
1352
1353 See also C<guestfs_stat>.");
1354
1355   ("is_dir", (RBool "dirflag", [Pathname "path"]), 38, [],
1356    [InitISOFS, Always, TestOutputFalse (
1357       [["is_dir"; "/known-3"]]);
1358     InitISOFS, Always, TestOutputTrue (
1359       [["is_dir"; "/directory"]])],
1360    "test if file exists",
1361    "\
1362 This returns C<true> if and only if there is a directory
1363 with the given C<path> name.  Note that it returns false for
1364 other objects like files.
1365
1366 See also C<guestfs_stat>.");
1367
1368   ("pvcreate", (RErr, [Device "device"]), 39, [],
1369    [InitEmpty, Always, TestOutputListOfDevices (
1370       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1371        ["pvcreate"; "/dev/sda1"];
1372        ["pvcreate"; "/dev/sda2"];
1373        ["pvcreate"; "/dev/sda3"];
1374        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1375    "create an LVM physical volume",
1376    "\
1377 This creates an LVM physical volume on the named C<device>,
1378 where C<device> should usually be a partition name such
1379 as C</dev/sda1>.");
1380
1381   ("vgcreate", (RErr, [String "volgroup"; DeviceList "physvols"]), 40, [],
1382    [InitEmpty, Always, TestOutputList (
1383       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1384        ["pvcreate"; "/dev/sda1"];
1385        ["pvcreate"; "/dev/sda2"];
1386        ["pvcreate"; "/dev/sda3"];
1387        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1388        ["vgcreate"; "VG2"; "/dev/sda3"];
1389        ["vgs"]], ["VG1"; "VG2"])],
1390    "create an LVM volume group",
1391    "\
1392 This creates an LVM volume group called C<volgroup>
1393 from the non-empty list of physical volumes C<physvols>.");
1394
1395   ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [],
1396    [InitEmpty, Always, TestOutputList (
1397       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1398        ["pvcreate"; "/dev/sda1"];
1399        ["pvcreate"; "/dev/sda2"];
1400        ["pvcreate"; "/dev/sda3"];
1401        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1402        ["vgcreate"; "VG2"; "/dev/sda3"];
1403        ["lvcreate"; "LV1"; "VG1"; "50"];
1404        ["lvcreate"; "LV2"; "VG1"; "50"];
1405        ["lvcreate"; "LV3"; "VG2"; "50"];
1406        ["lvcreate"; "LV4"; "VG2"; "50"];
1407        ["lvcreate"; "LV5"; "VG2"; "50"];
1408        ["lvs"]],
1409       ["/dev/VG1/LV1"; "/dev/VG1/LV2";
1410        "/dev/VG2/LV3"; "/dev/VG2/LV4"; "/dev/VG2/LV5"])],
1411    "create an LVM volume group",
1412    "\
1413 This creates an LVM volume group called C<logvol>
1414 on the volume group C<volgroup>, with C<size> megabytes.");
1415
1416   ("mkfs", (RErr, [String "fstype"; Device "device"]), 42, [],
1417    [InitEmpty, Always, TestOutput (
1418       [["part_disk"; "/dev/sda"; "mbr"];
1419        ["mkfs"; "ext2"; "/dev/sda1"];
1420        ["mount"; "/dev/sda1"; "/"];
1421        ["write_file"; "/new"; "new file contents"; "0"];
1422        ["cat"; "/new"]], "new file contents")],
1423    "make a filesystem",
1424    "\
1425 This creates a filesystem on C<device> (usually a partition
1426 or LVM logical volume).  The filesystem type is C<fstype>, for
1427 example C<ext3>.");
1428
1429   ("sfdisk", (RErr, [Device "device";
1430                      Int "cyls"; Int "heads"; Int "sectors";
1431                      StringList "lines"]), 43, [DangerWillRobinson],
1432    [],
1433    "create partitions on a block device",
1434    "\
1435 This is a direct interface to the L<sfdisk(8)> program for creating
1436 partitions on block devices.
1437
1438 C<device> should be a block device, for example C</dev/sda>.
1439
1440 C<cyls>, C<heads> and C<sectors> are the number of cylinders, heads
1441 and sectors on the device, which are passed directly to sfdisk as
1442 the I<-C>, I<-H> and I<-S> parameters.  If you pass C<0> for any
1443 of these, then the corresponding parameter is omitted.  Usually for
1444 'large' disks, you can just pass C<0> for these, but for small
1445 (floppy-sized) disks, sfdisk (or rather, the kernel) cannot work
1446 out the right geometry and you will need to tell it.
1447
1448 C<lines> is a list of lines that we feed to C<sfdisk>.  For more
1449 information refer to the L<sfdisk(8)> manpage.
1450
1451 To create a single partition occupying the whole disk, you would
1452 pass C<lines> as a single element list, when the single element being
1453 the string C<,> (comma).
1454
1455 See also: C<guestfs_sfdisk_l>, C<guestfs_sfdisk_N>,
1456 C<guestfs_part_init>");
1457
1458   ("write_file", (RErr, [Pathname "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning],
1459    [InitBasicFS, Always, TestOutput (
1460       [["write_file"; "/new"; "new file contents"; "0"];
1461        ["cat"; "/new"]], "new file contents");
1462     InitBasicFS, Always, TestOutput (
1463       [["write_file"; "/new"; "\nnew file contents\n"; "0"];
1464        ["cat"; "/new"]], "\nnew file contents\n");
1465     InitBasicFS, Always, TestOutput (
1466       [["write_file"; "/new"; "\n\n"; "0"];
1467        ["cat"; "/new"]], "\n\n");
1468     InitBasicFS, Always, TestOutput (
1469       [["write_file"; "/new"; ""; "0"];
1470        ["cat"; "/new"]], "");
1471     InitBasicFS, Always, TestOutput (
1472       [["write_file"; "/new"; "\n\n\n"; "0"];
1473        ["cat"; "/new"]], "\n\n\n");
1474     InitBasicFS, Always, TestOutput (
1475       [["write_file"; "/new"; "\n"; "0"];
1476        ["cat"; "/new"]], "\n")],
1477    "create a file",
1478    "\
1479 This call creates a file called C<path>.  The contents of the
1480 file is the string C<content> (which can contain any 8 bit data),
1481 with length C<size>.
1482
1483 As a special case, if C<size> is C<0>
1484 then the length is calculated using C<strlen> (so in this case
1485 the content cannot contain embedded ASCII NULs).
1486
1487 I<NB.> Owing to a bug, writing content containing ASCII NUL
1488 characters does I<not> work, even if the length is specified.
1489 We hope to resolve this bug in a future version.  In the meantime
1490 use C<guestfs_upload>.");
1491
1492   ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"],
1493    [InitEmpty, Always, TestOutputListOfDevices (
1494       [["part_disk"; "/dev/sda"; "mbr"];
1495        ["mkfs"; "ext2"; "/dev/sda1"];
1496        ["mount"; "/dev/sda1"; "/"];
1497        ["mounts"]], ["/dev/sda1"]);
1498     InitEmpty, Always, TestOutputList (
1499       [["part_disk"; "/dev/sda"; "mbr"];
1500        ["mkfs"; "ext2"; "/dev/sda1"];
1501        ["mount"; "/dev/sda1"; "/"];
1502        ["umount"; "/"];
1503        ["mounts"]], [])],
1504    "unmount a filesystem",
1505    "\
1506 This unmounts the given filesystem.  The filesystem may be
1507 specified either by its mountpoint (path) or the device which
1508 contains the filesystem.");
1509
1510   ("mounts", (RStringList "devices", []), 46, [],
1511    [InitBasicFS, Always, TestOutputListOfDevices (
1512       [["mounts"]], ["/dev/sda1"])],
1513    "show mounted filesystems",
1514    "\
1515 This returns the list of currently mounted filesystems.  It returns
1516 the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
1517
1518 Some internal mounts are not shown.
1519
1520 See also: C<guestfs_mountpoints>");
1521
1522   ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"],
1523    [InitBasicFS, Always, TestOutputList (
1524       [["umount_all"];
1525        ["mounts"]], []);
1526     (* check that umount_all can unmount nested mounts correctly: *)
1527     InitEmpty, Always, TestOutputList (
1528       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1529        ["mkfs"; "ext2"; "/dev/sda1"];
1530        ["mkfs"; "ext2"; "/dev/sda2"];
1531        ["mkfs"; "ext2"; "/dev/sda3"];
1532        ["mount"; "/dev/sda1"; "/"];
1533        ["mkdir"; "/mp1"];
1534        ["mount"; "/dev/sda2"; "/mp1"];
1535        ["mkdir"; "/mp1/mp2"];
1536        ["mount"; "/dev/sda3"; "/mp1/mp2"];
1537        ["mkdir"; "/mp1/mp2/mp3"];
1538        ["umount_all"];
1539        ["mounts"]], [])],
1540    "unmount all filesystems",
1541    "\
1542 This unmounts all mounted filesystems.
1543
1544 Some internal mounts are not unmounted by this call.");
1545
1546   ("lvm_remove_all", (RErr, []), 48, [DangerWillRobinson],
1547    [],
1548    "remove all LVM LVs, VGs and PVs",
1549    "\
1550 This command removes all LVM logical volumes, volume groups
1551 and physical volumes.");
1552
1553   ("file", (RString "description", [Dev_or_Path "path"]), 49, [],
1554    [InitISOFS, Always, TestOutput (
1555       [["file"; "/empty"]], "empty");
1556     InitISOFS, Always, TestOutput (
1557       [["file"; "/known-1"]], "ASCII text");
1558     InitISOFS, Always, TestLastFail (
1559       [["file"; "/notexists"]])],
1560    "determine file type",
1561    "\
1562 This call uses the standard L<file(1)> command to determine
1563 the type or contents of the file.  This also works on devices,
1564 for example to find out whether a partition contains a filesystem.
1565
1566 This call will also transparently look inside various types
1567 of compressed file.
1568
1569 The exact command which runs is C<file -zbsL path>.  Note in
1570 particular that the filename is not prepended to the output
1571 (the C<-b> option).");
1572
1573   ("command", (RString "output", [StringList "arguments"]), 50, [ProtocolLimitWarning],
1574    [InitBasicFS, Always, TestOutput (
1575       [["upload"; "test-command"; "/test-command"];
1576        ["chmod"; "0o755"; "/test-command"];
1577        ["command"; "/test-command 1"]], "Result1");
1578     InitBasicFS, Always, TestOutput (
1579       [["upload"; "test-command"; "/test-command"];
1580        ["chmod"; "0o755"; "/test-command"];
1581        ["command"; "/test-command 2"]], "Result2\n");
1582     InitBasicFS, Always, TestOutput (
1583       [["upload"; "test-command"; "/test-command"];
1584        ["chmod"; "0o755"; "/test-command"];
1585        ["command"; "/test-command 3"]], "\nResult3");
1586     InitBasicFS, Always, TestOutput (
1587       [["upload"; "test-command"; "/test-command"];
1588        ["chmod"; "0o755"; "/test-command"];
1589        ["command"; "/test-command 4"]], "\nResult4\n");
1590     InitBasicFS, Always, TestOutput (
1591       [["upload"; "test-command"; "/test-command"];
1592        ["chmod"; "0o755"; "/test-command"];
1593        ["command"; "/test-command 5"]], "\nResult5\n\n");
1594     InitBasicFS, Always, TestOutput (
1595       [["upload"; "test-command"; "/test-command"];
1596        ["chmod"; "0o755"; "/test-command"];
1597        ["command"; "/test-command 6"]], "\n\nResult6\n\n");
1598     InitBasicFS, Always, TestOutput (
1599       [["upload"; "test-command"; "/test-command"];
1600        ["chmod"; "0o755"; "/test-command"];
1601        ["command"; "/test-command 7"]], "");
1602     InitBasicFS, Always, TestOutput (
1603       [["upload"; "test-command"; "/test-command"];
1604        ["chmod"; "0o755"; "/test-command"];
1605        ["command"; "/test-command 8"]], "\n");
1606     InitBasicFS, Always, TestOutput (
1607       [["upload"; "test-command"; "/test-command"];
1608        ["chmod"; "0o755"; "/test-command"];
1609        ["command"; "/test-command 9"]], "\n\n");
1610     InitBasicFS, Always, TestOutput (
1611       [["upload"; "test-command"; "/test-command"];
1612        ["chmod"; "0o755"; "/test-command"];
1613        ["command"; "/test-command 10"]], "Result10-1\nResult10-2\n");
1614     InitBasicFS, Always, TestOutput (
1615       [["upload"; "test-command"; "/test-command"];
1616        ["chmod"; "0o755"; "/test-command"];
1617        ["command"; "/test-command 11"]], "Result11-1\nResult11-2");
1618     InitBasicFS, Always, TestLastFail (
1619       [["upload"; "test-command"; "/test-command"];
1620        ["chmod"; "0o755"; "/test-command"];
1621        ["command"; "/test-command"]])],
1622    "run a command from the guest filesystem",
1623    "\
1624 This call runs a command from the guest filesystem.  The
1625 filesystem must be mounted, and must contain a compatible
1626 operating system (ie. something Linux, with the same
1627 or compatible processor architecture).
1628
1629 The single parameter is an argv-style list of arguments.
1630 The first element is the name of the program to run.
1631 Subsequent elements are parameters.  The list must be
1632 non-empty (ie. must contain a program name).  Note that
1633 the command runs directly, and is I<not> invoked via
1634 the shell (see C<guestfs_sh>).
1635
1636 The return value is anything printed to I<stdout> by
1637 the command.
1638
1639 If the command returns a non-zero exit status, then
1640 this function returns an error message.  The error message
1641 string is the content of I<stderr> from the command.
1642
1643 The C<$PATH> environment variable will contain at least
1644 C</usr/bin> and C</bin>.  If you require a program from
1645 another location, you should provide the full path in the
1646 first parameter.
1647
1648 Shared libraries and data files required by the program
1649 must be available on filesystems which are mounted in the
1650 correct places.  It is the caller's responsibility to ensure
1651 all filesystems that are needed are mounted at the right
1652 locations.");
1653
1654   ("command_lines", (RStringList "lines", [StringList "arguments"]), 51, [ProtocolLimitWarning],
1655    [InitBasicFS, Always, TestOutputList (
1656       [["upload"; "test-command"; "/test-command"];
1657        ["chmod"; "0o755"; "/test-command"];
1658        ["command_lines"; "/test-command 1"]], ["Result1"]);
1659     InitBasicFS, Always, TestOutputList (
1660       [["upload"; "test-command"; "/test-command"];
1661        ["chmod"; "0o755"; "/test-command"];
1662        ["command_lines"; "/test-command 2"]], ["Result2"]);
1663     InitBasicFS, Always, TestOutputList (
1664       [["upload"; "test-command"; "/test-command"];
1665        ["chmod"; "0o755"; "/test-command"];
1666        ["command_lines"; "/test-command 3"]], ["";"Result3"]);
1667     InitBasicFS, Always, TestOutputList (
1668       [["upload"; "test-command"; "/test-command"];
1669        ["chmod"; "0o755"; "/test-command"];
1670        ["command_lines"; "/test-command 4"]], ["";"Result4"]);
1671     InitBasicFS, Always, TestOutputList (
1672       [["upload"; "test-command"; "/test-command"];
1673        ["chmod"; "0o755"; "/test-command"];
1674        ["command_lines"; "/test-command 5"]], ["";"Result5";""]);
1675     InitBasicFS, Always, TestOutputList (
1676       [["upload"; "test-command"; "/test-command"];
1677        ["chmod"; "0o755"; "/test-command"];
1678        ["command_lines"; "/test-command 6"]], ["";"";"Result6";""]);
1679     InitBasicFS, Always, TestOutputList (
1680       [["upload"; "test-command"; "/test-command"];
1681        ["chmod"; "0o755"; "/test-command"];
1682        ["command_lines"; "/test-command 7"]], []);
1683     InitBasicFS, Always, TestOutputList (
1684       [["upload"; "test-command"; "/test-command"];
1685        ["chmod"; "0o755"; "/test-command"];
1686        ["command_lines"; "/test-command 8"]], [""]);
1687     InitBasicFS, Always, TestOutputList (
1688       [["upload"; "test-command"; "/test-command"];
1689        ["chmod"; "0o755"; "/test-command"];
1690        ["command_lines"; "/test-command 9"]], ["";""]);
1691     InitBasicFS, Always, TestOutputList (
1692       [["upload"; "test-command"; "/test-command"];
1693        ["chmod"; "0o755"; "/test-command"];
1694        ["command_lines"; "/test-command 10"]], ["Result10-1";"Result10-2"]);
1695     InitBasicFS, Always, TestOutputList (
1696       [["upload"; "test-command"; "/test-command"];
1697        ["chmod"; "0o755"; "/test-command"];
1698        ["command_lines"; "/test-command 11"]], ["Result11-1";"Result11-2"])],
1699    "run a command, returning lines",
1700    "\
1701 This is the same as C<guestfs_command>, but splits the
1702 result into a list of lines.
1703
1704 See also: C<guestfs_sh_lines>");
1705
1706   ("stat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 52, [],
1707    [InitISOFS, Always, TestOutputStruct (
1708       [["stat"; "/empty"]], [CompareWithInt ("size", 0)])],
1709    "get file information",
1710    "\
1711 Returns file information for the given C<path>.
1712
1713 This is the same as the C<stat(2)> system call.");
1714
1715   ("lstat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 53, [],
1716    [InitISOFS, Always, TestOutputStruct (
1717       [["lstat"; "/empty"]], [CompareWithInt ("size", 0)])],
1718    "get file information for a symbolic link",
1719    "\
1720 Returns file information for the given C<path>.
1721
1722 This is the same as C<guestfs_stat> except that if C<path>
1723 is a symbolic link, then the link is stat-ed, not the file it
1724 refers to.
1725
1726 This is the same as the C<lstat(2)> system call.");
1727
1728   ("statvfs", (RStruct ("statbuf", "statvfs"), [Pathname "path"]), 54, [],
1729    [InitISOFS, Always, TestOutputStruct (
1730       [["statvfs"; "/"]], [CompareWithInt ("namemax", 255)])],
1731    "get file system statistics",
1732    "\
1733 Returns file system statistics for any mounted file system.
1734 C<path> should be a file or directory in the mounted file system
1735 (typically it is the mount point itself, but it doesn't need to be).
1736
1737 This is the same as the C<statvfs(2)> system call.");
1738
1739   ("tune2fs_l", (RHashtable "superblock", [Device "device"]), 55, [],
1740    [], (* XXX test *)
1741    "get ext2/ext3/ext4 superblock details",
1742    "\
1743 This returns the contents of the ext2, ext3 or ext4 filesystem
1744 superblock on C<device>.
1745
1746 It is the same as running C<tune2fs -l device>.  See L<tune2fs(8)>
1747 manpage for more details.  The list of fields returned isn't
1748 clearly defined, and depends on both the version of C<tune2fs>
1749 that libguestfs was built against, and the filesystem itself.");
1750
1751   ("blockdev_setro", (RErr, [Device "device"]), 56, [],
1752    [InitEmpty, Always, TestOutputTrue (
1753       [["blockdev_setro"; "/dev/sda"];
1754        ["blockdev_getro"; "/dev/sda"]])],
1755    "set block device to read-only",
1756    "\
1757 Sets the block device named C<device> to read-only.
1758
1759 This uses the L<blockdev(8)> command.");
1760
1761   ("blockdev_setrw", (RErr, [Device "device"]), 57, [],
1762    [InitEmpty, Always, TestOutputFalse (
1763       [["blockdev_setrw"; "/dev/sda"];
1764        ["blockdev_getro"; "/dev/sda"]])],
1765    "set block device to read-write",
1766    "\
1767 Sets the block device named C<device> to read-write.
1768
1769 This uses the L<blockdev(8)> command.");
1770
1771   ("blockdev_getro", (RBool "ro", [Device "device"]), 58, [],
1772    [InitEmpty, Always, TestOutputTrue (
1773       [["blockdev_setro"; "/dev/sda"];
1774        ["blockdev_getro"; "/dev/sda"]])],
1775    "is block device set to read-only",
1776    "\
1777 Returns a boolean indicating if the block device is read-only
1778 (true if read-only, false if not).
1779
1780 This uses the L<blockdev(8)> command.");
1781
1782   ("blockdev_getss", (RInt "sectorsize", [Device "device"]), 59, [],
1783    [InitEmpty, Always, TestOutputInt (
1784       [["blockdev_getss"; "/dev/sda"]], 512)],
1785    "get sectorsize of block device",
1786    "\
1787 This returns the size of sectors on a block device.
1788 Usually 512, but can be larger for modern devices.
1789
1790 (Note, this is not the size in sectors, use C<guestfs_blockdev_getsz>
1791 for that).
1792
1793 This uses the L<blockdev(8)> command.");
1794
1795   ("blockdev_getbsz", (RInt "blocksize", [Device "device"]), 60, [],
1796    [InitEmpty, Always, TestOutputInt (
1797       [["blockdev_getbsz"; "/dev/sda"]], 4096)],
1798    "get blocksize of block device",
1799    "\
1800 This returns the block size of a device.
1801
1802 (Note this is different from both I<size in blocks> and
1803 I<filesystem block size>).
1804
1805 This uses the L<blockdev(8)> command.");
1806
1807   ("blockdev_setbsz", (RErr, [Device "device"; Int "blocksize"]), 61, [],
1808    [], (* XXX test *)
1809    "set blocksize of block device",
1810    "\
1811 This sets the block size of a device.
1812
1813 (Note this is different from both I<size in blocks> and
1814 I<filesystem block size>).
1815
1816 This uses the L<blockdev(8)> command.");
1817
1818   ("blockdev_getsz", (RInt64 "sizeinsectors", [Device "device"]), 62, [],
1819    [InitEmpty, Always, TestOutputInt (
1820       [["blockdev_getsz"; "/dev/sda"]], 1024000)],
1821    "get total size of device in 512-byte sectors",
1822    "\
1823 This returns the size of the device in units of 512-byte sectors
1824 (even if the sectorsize isn't 512 bytes ... weird).
1825
1826 See also C<guestfs_blockdev_getss> for the real sector size of
1827 the device, and C<guestfs_blockdev_getsize64> for the more
1828 useful I<size in bytes>.
1829
1830 This uses the L<blockdev(8)> command.");
1831
1832   ("blockdev_getsize64", (RInt64 "sizeinbytes", [Device "device"]), 63, [],
1833    [InitEmpty, Always, TestOutputInt (
1834       [["blockdev_getsize64"; "/dev/sda"]], 524288000)],
1835    "get total size of device in bytes",
1836    "\
1837 This returns the size of the device in bytes.
1838
1839 See also C<guestfs_blockdev_getsz>.
1840
1841 This uses the L<blockdev(8)> command.");
1842
1843   ("blockdev_flushbufs", (RErr, [Device "device"]), 64, [],
1844    [InitEmpty, Always, TestRun
1845       [["blockdev_flushbufs"; "/dev/sda"]]],
1846    "flush device buffers",
1847    "\
1848 This tells the kernel to flush internal buffers associated
1849 with C<device>.
1850
1851 This uses the L<blockdev(8)> command.");
1852
1853   ("blockdev_rereadpt", (RErr, [Device "device"]), 65, [],
1854    [InitEmpty, Always, TestRun
1855       [["blockdev_rereadpt"; "/dev/sda"]]],
1856    "reread partition table",
1857    "\
1858 Reread the partition table on C<device>.
1859
1860 This uses the L<blockdev(8)> command.");
1861
1862   ("upload", (RErr, [FileIn "filename"; String "remotefilename"]), 66, [],
1863    [InitBasicFS, Always, TestOutput (
1864       (* Pick a file from cwd which isn't likely to change. *)
1865       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1866        ["checksum"; "md5"; "/COPYING.LIB"]],
1867         Digest.to_hex (Digest.file "COPYING.LIB"))],
1868    "upload a file from the local machine",
1869    "\
1870 Upload local file C<filename> to C<remotefilename> on the
1871 filesystem.
1872
1873 C<filename> can also be a named pipe.
1874
1875 See also C<guestfs_download>.");
1876
1877   ("download", (RErr, [Dev_or_Path "remotefilename"; FileOut "filename"]), 67, [],
1878    [InitBasicFS, Always, TestOutput (
1879       (* Pick a file from cwd which isn't likely to change. *)
1880       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1881        ["download"; "/COPYING.LIB"; "testdownload.tmp"];
1882        ["upload"; "testdownload.tmp"; "/upload"];
1883        ["checksum"; "md5"; "/upload"]],
1884         Digest.to_hex (Digest.file "COPYING.LIB"))],
1885    "download a file to the local machine",
1886    "\
1887 Download file C<remotefilename> and save it as C<filename>
1888 on the local machine.
1889
1890 C<filename> can also be a named pipe.
1891
1892 See also C<guestfs_upload>, C<guestfs_cat>.");
1893
1894   ("checksum", (RString "checksum", [String "csumtype"; Pathname "path"]), 68, [],
1895    [InitISOFS, Always, TestOutput (
1896       [["checksum"; "crc"; "/known-3"]], "2891671662");
1897     InitISOFS, Always, TestLastFail (
1898       [["checksum"; "crc"; "/notexists"]]);
1899     InitISOFS, Always, TestOutput (
1900       [["checksum"; "md5"; "/known-3"]], "46d6ca27ee07cdc6fa99c2e138cc522c");
1901     InitISOFS, Always, TestOutput (
1902       [["checksum"; "sha1"; "/known-3"]], "b7ebccc3ee418311091c3eda0a45b83c0a770f15");
1903     InitISOFS, Always, TestOutput (
1904       [["checksum"; "sha224"; "/known-3"]], "d2cd1774b28f3659c14116be0a6dc2bb5c4b350ce9cd5defac707741");
1905     InitISOFS, Always, TestOutput (
1906       [["checksum"; "sha256"; "/known-3"]], "75bb71b90cd20cb13f86d2bea8dad63ac7194e7517c3b52b8d06ff52d3487d30");
1907     InitISOFS, Always, TestOutput (
1908       [["checksum"; "sha384"; "/known-3"]], "5fa7883430f357b5d7b7271d3a1d2872b51d73cba72731de6863d3dea55f30646af2799bef44d5ea776a5ec7941ac640");
1909     InitISOFS, Always, TestOutput (
1910       [["checksum"; "sha512"; "/known-3"]], "2794062c328c6b216dca90443b7f7134c5f40e56bd0ed7853123275a09982a6f992e6ca682f9d2fba34a4c5e870d8fe077694ff831e3032a004ee077e00603f6")],
1911    "compute MD5, SHAx or CRC checksum of file",
1912    "\
1913 This call computes the MD5, SHAx or CRC checksum of the
1914 file named C<path>.
1915
1916 The type of checksum to compute is given by the C<csumtype>
1917 parameter which must have one of the following values:
1918
1919 =over 4
1920
1921 =item C<crc>
1922
1923 Compute the cyclic redundancy check (CRC) specified by POSIX
1924 for the C<cksum> command.
1925
1926 =item C<md5>
1927
1928 Compute the MD5 hash (using the C<md5sum> program).
1929
1930 =item C<sha1>
1931
1932 Compute the SHA1 hash (using the C<sha1sum> program).
1933
1934 =item C<sha224>
1935
1936 Compute the SHA224 hash (using the C<sha224sum> program).
1937
1938 =item C<sha256>
1939
1940 Compute the SHA256 hash (using the C<sha256sum> program).
1941
1942 =item C<sha384>
1943
1944 Compute the SHA384 hash (using the C<sha384sum> program).
1945
1946 =item C<sha512>
1947
1948 Compute the SHA512 hash (using the C<sha512sum> program).
1949
1950 =back
1951
1952 The checksum is returned as a printable string.");
1953
1954   ("tar_in", (RErr, [FileIn "tarfile"; String "directory"]), 69, [],
1955    [InitBasicFS, Always, TestOutput (
1956       [["tar_in"; "../images/helloworld.tar"; "/"];
1957        ["cat"; "/hello"]], "hello\n")],
1958    "unpack tarfile to directory",
1959    "\
1960 This command uploads and unpacks local file C<tarfile> (an
1961 I<uncompressed> tar file) into C<directory>.
1962
1963 To upload a compressed tarball, use C<guestfs_tgz_in>.");
1964
1965   ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [],
1966    [],
1967    "pack directory into tarfile",
1968    "\
1969 This command packs the contents of C<directory> and downloads
1970 it to local file C<tarfile>.
1971
1972 To download a compressed tarball, use C<guestfs_tgz_out>.");
1973
1974   ("tgz_in", (RErr, [FileIn "tarball"; String "directory"]), 71, [],
1975    [InitBasicFS, Always, TestOutput (
1976       [["tgz_in"; "../images/helloworld.tar.gz"; "/"];
1977        ["cat"; "/hello"]], "hello\n")],
1978    "unpack compressed tarball to directory",
1979    "\
1980 This command uploads and unpacks local file C<tarball> (a
1981 I<gzip compressed> tar file) into C<directory>.
1982
1983 To upload an uncompressed tarball, use C<guestfs_tar_in>.");
1984
1985   ("tgz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 72, [],
1986    [],
1987    "pack directory into compressed tarball",
1988    "\
1989 This command packs the contents of C<directory> and downloads
1990 it to local file C<tarball>.
1991
1992 To download an uncompressed tarball, use C<guestfs_tar_out>.");
1993
1994   ("mount_ro", (RErr, [Device "device"; String "mountpoint"]), 73, [],
1995    [InitBasicFS, Always, TestLastFail (
1996       [["umount"; "/"];
1997        ["mount_ro"; "/dev/sda1"; "/"];
1998        ["touch"; "/new"]]);
1999     InitBasicFS, Always, TestOutput (
2000       [["write_file"; "/new"; "data"; "0"];
2001        ["umount"; "/"];
2002        ["mount_ro"; "/dev/sda1"; "/"];
2003        ["cat"; "/new"]], "data")],
2004    "mount a guest disk, read-only",
2005    "\
2006 This is the same as the C<guestfs_mount> command, but it
2007 mounts the filesystem with the read-only (I<-o ro>) flag.");
2008
2009   ("mount_options", (RErr, [String "options"; Device "device"; String "mountpoint"]), 74, [],
2010    [],
2011    "mount a guest disk with mount options",
2012    "\
2013 This is the same as the C<guestfs_mount> command, but it
2014 allows you to set the mount options as for the
2015 L<mount(8)> I<-o> flag.");
2016
2017   ("mount_vfs", (RErr, [String "options"; String "vfstype"; Device "device"; String "mountpoint"]), 75, [],
2018    [],
2019    "mount a guest disk with mount options and vfstype",
2020    "\
2021 This is the same as the C<guestfs_mount> command, but it
2022 allows you to set both the mount options and the vfstype
2023 as for the L<mount(8)> I<-o> and I<-t> flags.");
2024
2025   ("debug", (RString "result", [String "subcmd"; StringList "extraargs"]), 76, [],
2026    [],
2027    "debugging and internals",
2028    "\
2029 The C<guestfs_debug> command exposes some internals of
2030 C<guestfsd> (the guestfs daemon) that runs inside the
2031 qemu subprocess.
2032
2033 There is no comprehensive help for this command.  You have
2034 to look at the file C<daemon/debug.c> in the libguestfs source
2035 to find out what you can do.");
2036
2037   ("lvremove", (RErr, [Device "device"]), 77, [],
2038    [InitEmpty, Always, TestOutputList (
2039       [["part_disk"; "/dev/sda"; "mbr"];
2040        ["pvcreate"; "/dev/sda1"];
2041        ["vgcreate"; "VG"; "/dev/sda1"];
2042        ["lvcreate"; "LV1"; "VG"; "50"];
2043        ["lvcreate"; "LV2"; "VG"; "50"];
2044        ["lvremove"; "/dev/VG/LV1"];
2045        ["lvs"]], ["/dev/VG/LV2"]);
2046     InitEmpty, Always, TestOutputList (
2047       [["part_disk"; "/dev/sda"; "mbr"];
2048        ["pvcreate"; "/dev/sda1"];
2049        ["vgcreate"; "VG"; "/dev/sda1"];
2050        ["lvcreate"; "LV1"; "VG"; "50"];
2051        ["lvcreate"; "LV2"; "VG"; "50"];
2052        ["lvremove"; "/dev/VG"];
2053        ["lvs"]], []);
2054     InitEmpty, Always, TestOutputList (
2055       [["part_disk"; "/dev/sda"; "mbr"];
2056        ["pvcreate"; "/dev/sda1"];
2057        ["vgcreate"; "VG"; "/dev/sda1"];
2058        ["lvcreate"; "LV1"; "VG"; "50"];
2059        ["lvcreate"; "LV2"; "VG"; "50"];
2060        ["lvremove"; "/dev/VG"];
2061        ["vgs"]], ["VG"])],
2062    "remove an LVM logical volume",
2063    "\
2064 Remove an LVM logical volume C<device>, where C<device> is
2065 the path to the LV, such as C</dev/VG/LV>.
2066
2067 You can also remove all LVs in a volume group by specifying
2068 the VG name, C</dev/VG>.");
2069
2070   ("vgremove", (RErr, [String "vgname"]), 78, [],
2071    [InitEmpty, Always, TestOutputList (
2072       [["part_disk"; "/dev/sda"; "mbr"];
2073        ["pvcreate"; "/dev/sda1"];
2074        ["vgcreate"; "VG"; "/dev/sda1"];
2075        ["lvcreate"; "LV1"; "VG"; "50"];
2076        ["lvcreate"; "LV2"; "VG"; "50"];
2077        ["vgremove"; "VG"];
2078        ["lvs"]], []);
2079     InitEmpty, Always, TestOutputList (
2080       [["part_disk"; "/dev/sda"; "mbr"];
2081        ["pvcreate"; "/dev/sda1"];
2082        ["vgcreate"; "VG"; "/dev/sda1"];
2083        ["lvcreate"; "LV1"; "VG"; "50"];
2084        ["lvcreate"; "LV2"; "VG"; "50"];
2085        ["vgremove"; "VG"];
2086        ["vgs"]], [])],
2087    "remove an LVM volume group",
2088    "\
2089 Remove an LVM volume group C<vgname>, (for example C<VG>).
2090
2091 This also forcibly removes all logical volumes in the volume
2092 group (if any).");
2093
2094   ("pvremove", (RErr, [Device "device"]), 79, [],
2095    [InitEmpty, Always, TestOutputListOfDevices (
2096       [["part_disk"; "/dev/sda"; "mbr"];
2097        ["pvcreate"; "/dev/sda1"];
2098        ["vgcreate"; "VG"; "/dev/sda1"];
2099        ["lvcreate"; "LV1"; "VG"; "50"];
2100        ["lvcreate"; "LV2"; "VG"; "50"];
2101        ["vgremove"; "VG"];
2102        ["pvremove"; "/dev/sda1"];
2103        ["lvs"]], []);
2104     InitEmpty, Always, TestOutputListOfDevices (
2105       [["part_disk"; "/dev/sda"; "mbr"];
2106        ["pvcreate"; "/dev/sda1"];
2107        ["vgcreate"; "VG"; "/dev/sda1"];
2108        ["lvcreate"; "LV1"; "VG"; "50"];
2109        ["lvcreate"; "LV2"; "VG"; "50"];
2110        ["vgremove"; "VG"];
2111        ["pvremove"; "/dev/sda1"];
2112        ["vgs"]], []);
2113     InitEmpty, Always, TestOutputListOfDevices (
2114       [["part_disk"; "/dev/sda"; "mbr"];
2115        ["pvcreate"; "/dev/sda1"];
2116        ["vgcreate"; "VG"; "/dev/sda1"];
2117        ["lvcreate"; "LV1"; "VG"; "50"];
2118        ["lvcreate"; "LV2"; "VG"; "50"];
2119        ["vgremove"; "VG"];
2120        ["pvremove"; "/dev/sda1"];
2121        ["pvs"]], [])],
2122    "remove an LVM physical volume",
2123    "\
2124 This wipes a physical volume C<device> so that LVM will no longer
2125 recognise it.
2126
2127 The implementation uses the C<pvremove> command which refuses to
2128 wipe physical volumes that contain any volume groups, so you have
2129 to remove those first.");
2130
2131   ("set_e2label", (RErr, [Device "device"; String "label"]), 80, [],
2132    [InitBasicFS, Always, TestOutput (
2133       [["set_e2label"; "/dev/sda1"; "testlabel"];
2134        ["get_e2label"; "/dev/sda1"]], "testlabel")],
2135    "set the ext2/3/4 filesystem label",
2136    "\
2137 This sets the ext2/3/4 filesystem label of the filesystem on
2138 C<device> to C<label>.  Filesystem labels are limited to
2139 16 characters.
2140
2141 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2label>
2142 to return the existing label on a filesystem.");
2143
2144   ("get_e2label", (RString "label", [Device "device"]), 81, [],
2145    [],
2146    "get the ext2/3/4 filesystem label",
2147    "\
2148 This returns the ext2/3/4 filesystem label of the filesystem on
2149 C<device>.");
2150
2151   ("set_e2uuid", (RErr, [Device "device"; String "uuid"]), 82, [],
2152    (let uuid = uuidgen () in
2153     [InitBasicFS, Always, TestOutput (
2154        [["set_e2uuid"; "/dev/sda1"; uuid];
2155         ["get_e2uuid"; "/dev/sda1"]], uuid);
2156      InitBasicFS, Always, TestOutput (
2157        [["set_e2uuid"; "/dev/sda1"; "clear"];
2158         ["get_e2uuid"; "/dev/sda1"]], "");
2159      (* We can't predict what UUIDs will be, so just check the commands run. *)
2160      InitBasicFS, Always, TestRun (
2161        [["set_e2uuid"; "/dev/sda1"; "random"]]);
2162      InitBasicFS, Always, TestRun (
2163        [["set_e2uuid"; "/dev/sda1"; "time"]])]),
2164    "set the ext2/3/4 filesystem UUID",
2165    "\
2166 This sets the ext2/3/4 filesystem UUID of the filesystem on
2167 C<device> to C<uuid>.  The format of the UUID and alternatives
2168 such as C<clear>, C<random> and C<time> are described in the
2169 L<tune2fs(8)> manpage.
2170
2171 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2uuid>
2172 to return the existing UUID of a filesystem.");
2173
2174   ("get_e2uuid", (RString "uuid", [Device "device"]), 83, [],
2175    [],
2176    "get the ext2/3/4 filesystem UUID",
2177    "\
2178 This returns the ext2/3/4 filesystem UUID of the filesystem on
2179 C<device>.");
2180
2181   ("fsck", (RInt "status", [String "fstype"; Device "device"]), 84, [],
2182    [InitBasicFS, Always, TestOutputInt (
2183       [["umount"; "/dev/sda1"];
2184        ["fsck"; "ext2"; "/dev/sda1"]], 0);
2185     InitBasicFS, Always, TestOutputInt (
2186       [["umount"; "/dev/sda1"];
2187        ["zero"; "/dev/sda1"];
2188        ["fsck"; "ext2"; "/dev/sda1"]], 8)],
2189    "run the filesystem checker",
2190    "\
2191 This runs the filesystem checker (fsck) on C<device> which
2192 should have filesystem type C<fstype>.
2193
2194 The returned integer is the status.  See L<fsck(8)> for the
2195 list of status codes from C<fsck>.
2196
2197 Notes:
2198
2199 =over 4
2200
2201 =item *
2202
2203 Multiple status codes can be summed together.
2204
2205 =item *
2206
2207 A non-zero return code can mean \"success\", for example if
2208 errors have been corrected on the filesystem.
2209
2210 =item *
2211
2212 Checking or repairing NTFS volumes is not supported
2213 (by linux-ntfs).
2214
2215 =back
2216
2217 This command is entirely equivalent to running C<fsck -a -t fstype device>.");
2218
2219   ("zero", (RErr, [Device "device"]), 85, [],
2220    [InitBasicFS, Always, TestOutput (
2221       [["umount"; "/dev/sda1"];
2222        ["zero"; "/dev/sda1"];
2223        ["file"; "/dev/sda1"]], "data")],
2224    "write zeroes to the device",
2225    "\
2226 This command writes zeroes over the first few blocks of C<device>.
2227
2228 How many blocks are zeroed isn't specified (but it's I<not> enough
2229 to securely wipe the device).  It should be sufficient to remove
2230 any partition tables, filesystem superblocks and so on.
2231
2232 See also: C<guestfs_scrub_device>.");
2233
2234   ("grub_install", (RErr, [Pathname "root"; Device "device"]), 86, [],
2235    (* Test disabled because grub-install incompatible with virtio-blk driver.
2236     * See also: https://bugzilla.redhat.com/show_bug.cgi?id=479760
2237     *)
2238    [InitBasicFS, Disabled, TestOutputTrue (
2239       [["grub_install"; "/"; "/dev/sda1"];
2240        ["is_dir"; "/boot"]])],
2241    "install GRUB",
2242    "\
2243 This command installs GRUB (the Grand Unified Bootloader) on
2244 C<device>, with the root directory being C<root>.");
2245
2246   ("cp", (RErr, [Pathname "src"; Pathname "dest"]), 87, [],
2247    [InitBasicFS, Always, TestOutput (
2248       [["write_file"; "/old"; "file content"; "0"];
2249        ["cp"; "/old"; "/new"];
2250        ["cat"; "/new"]], "file content");
2251     InitBasicFS, Always, TestOutputTrue (
2252       [["write_file"; "/old"; "file content"; "0"];
2253        ["cp"; "/old"; "/new"];
2254        ["is_file"; "/old"]]);
2255     InitBasicFS, Always, TestOutput (
2256       [["write_file"; "/old"; "file content"; "0"];
2257        ["mkdir"; "/dir"];
2258        ["cp"; "/old"; "/dir/new"];
2259        ["cat"; "/dir/new"]], "file content")],
2260    "copy a file",
2261    "\
2262 This copies a file from C<src> to C<dest> where C<dest> is
2263 either a destination filename or destination directory.");
2264
2265   ("cp_a", (RErr, [Pathname "src"; Pathname "dest"]), 88, [],
2266    [InitBasicFS, Always, TestOutput (
2267       [["mkdir"; "/olddir"];
2268        ["mkdir"; "/newdir"];
2269        ["write_file"; "/olddir/file"; "file content"; "0"];
2270        ["cp_a"; "/olddir"; "/newdir"];
2271        ["cat"; "/newdir/olddir/file"]], "file content")],
2272    "copy a file or directory recursively",
2273    "\
2274 This copies a file or directory from C<src> to C<dest>
2275 recursively using the C<cp -a> command.");
2276
2277   ("mv", (RErr, [Pathname "src"; Pathname "dest"]), 89, [],
2278    [InitBasicFS, Always, TestOutput (
2279       [["write_file"; "/old"; "file content"; "0"];
2280        ["mv"; "/old"; "/new"];
2281        ["cat"; "/new"]], "file content");
2282     InitBasicFS, Always, TestOutputFalse (
2283       [["write_file"; "/old"; "file content"; "0"];
2284        ["mv"; "/old"; "/new"];
2285        ["is_file"; "/old"]])],
2286    "move a file",
2287    "\
2288 This moves a file from C<src> to C<dest> where C<dest> is
2289 either a destination filename or destination directory.");
2290
2291   ("drop_caches", (RErr, [Int "whattodrop"]), 90, [],
2292    [InitEmpty, Always, TestRun (
2293       [["drop_caches"; "3"]])],
2294    "drop kernel page cache, dentries and inodes",
2295    "\
2296 This instructs the guest kernel to drop its page cache,
2297 and/or dentries and inode caches.  The parameter C<whattodrop>
2298 tells the kernel what precisely to drop, see
2299 L<http://linux-mm.org/Drop_Caches>
2300
2301 Setting C<whattodrop> to 3 should drop everything.
2302
2303 This automatically calls L<sync(2)> before the operation,
2304 so that the maximum guest memory is freed.");
2305
2306   ("dmesg", (RString "kmsgs", []), 91, [],
2307    [InitEmpty, Always, TestRun (
2308       [["dmesg"]])],
2309    "return kernel messages",
2310    "\
2311 This returns the kernel messages (C<dmesg> output) from
2312 the guest kernel.  This is sometimes useful for extended
2313 debugging of problems.
2314
2315 Another way to get the same information is to enable
2316 verbose messages with C<guestfs_set_verbose> or by setting
2317 the environment variable C<LIBGUESTFS_DEBUG=1> before
2318 running the program.");
2319
2320   ("ping_daemon", (RErr, []), 92, [],
2321    [InitEmpty, Always, TestRun (
2322       [["ping_daemon"]])],
2323    "ping the guest daemon",
2324    "\
2325 This is a test probe into the guestfs daemon running inside
2326 the qemu subprocess.  Calling this function checks that the
2327 daemon responds to the ping message, without affecting the daemon
2328 or attached block device(s) in any other way.");
2329
2330   ("equal", (RBool "equality", [Pathname "file1"; Pathname "file2"]), 93, [],
2331    [InitBasicFS, Always, TestOutputTrue (
2332       [["write_file"; "/file1"; "contents of a file"; "0"];
2333        ["cp"; "/file1"; "/file2"];
2334        ["equal"; "/file1"; "/file2"]]);
2335     InitBasicFS, Always, TestOutputFalse (
2336       [["write_file"; "/file1"; "contents of a file"; "0"];
2337        ["write_file"; "/file2"; "contents of another file"; "0"];
2338        ["equal"; "/file1"; "/file2"]]);
2339     InitBasicFS, Always, TestLastFail (
2340       [["equal"; "/file1"; "/file2"]])],
2341    "test if two files have equal contents",
2342    "\
2343 This compares the two files C<file1> and C<file2> and returns
2344 true if their content is exactly equal, or false otherwise.
2345
2346 The external L<cmp(1)> program is used for the comparison.");
2347
2348   ("strings", (RStringList "stringsout", [Pathname "path"]), 94, [ProtocolLimitWarning],
2349    [InitISOFS, Always, TestOutputList (
2350       [["strings"; "/known-5"]], ["abcdefghi"; "jklmnopqr"]);
2351     InitISOFS, Always, TestOutputList (
2352       [["strings"; "/empty"]], [])],
2353    "print the printable strings in a file",
2354    "\
2355 This runs the L<strings(1)> command on a file and returns
2356 the list of printable strings found.");
2357
2358   ("strings_e", (RStringList "stringsout", [String "encoding"; Pathname "path"]), 95, [ProtocolLimitWarning],
2359    [InitISOFS, Always, TestOutputList (
2360       [["strings_e"; "b"; "/known-5"]], []);
2361     InitBasicFS, Disabled, TestOutputList (
2362       [["write_file"; "/new"; "\000h\000e\000l\000l\000o\000\n\000w\000o\000r\000l\000d\000\n"; "24"];
2363        ["strings_e"; "b"; "/new"]], ["hello"; "world"])],
2364    "print the printable strings in a file",
2365    "\
2366 This is like the C<guestfs_strings> command, but allows you to
2367 specify the encoding.
2368
2369 See the L<strings(1)> manpage for the full list of encodings.
2370
2371 Commonly useful encodings are C<l> (lower case L) which will
2372 show strings inside Windows/x86 files.
2373
2374 The returned strings are transcoded to UTF-8.");
2375
2376   ("hexdump", (RString "dump", [Pathname "path"]), 96, [ProtocolLimitWarning],
2377    [InitISOFS, Always, TestOutput (
2378       [["hexdump"; "/known-4"]], "00000000  61 62 63 0a 64 65 66 0a  67 68 69                 |abc.def.ghi|\n0000000b\n");
2379     (* Test for RHBZ#501888c2 regression which caused large hexdump
2380      * commands to segfault.
2381      *)
2382     InitISOFS, Always, TestRun (
2383       [["hexdump"; "/100krandom"]])],
2384    "dump a file in hexadecimal",
2385    "\
2386 This runs C<hexdump -C> on the given C<path>.  The result is
2387 the human-readable, canonical hex dump of the file.");
2388
2389   ("zerofree", (RErr, [Device "device"]), 97, [],
2390    [InitNone, Always, TestOutput (
2391       [["part_disk"; "/dev/sda"; "mbr"];
2392        ["mkfs"; "ext3"; "/dev/sda1"];
2393        ["mount"; "/dev/sda1"; "/"];
2394        ["write_file"; "/new"; "test file"; "0"];
2395        ["umount"; "/dev/sda1"];
2396        ["zerofree"; "/dev/sda1"];
2397        ["mount"; "/dev/sda1"; "/"];
2398        ["cat"; "/new"]], "test file")],
2399    "zero unused inodes and disk blocks on ext2/3 filesystem",
2400    "\
2401 This runs the I<zerofree> program on C<device>.  This program
2402 claims to zero unused inodes and disk blocks on an ext2/3
2403 filesystem, thus making it possible to compress the filesystem
2404 more effectively.
2405
2406 You should B<not> run this program if the filesystem is
2407 mounted.
2408
2409 It is possible that using this program can damage the filesystem
2410 or data on the filesystem.");
2411
2412   ("pvresize", (RErr, [Device "device"]), 98, [],
2413    [],
2414    "resize an LVM physical volume",
2415    "\
2416 This resizes (expands or shrinks) an existing LVM physical
2417 volume to match the new size of the underlying device.");
2418
2419   ("sfdisk_N", (RErr, [Device "device"; Int "partnum";
2420                        Int "cyls"; Int "heads"; Int "sectors";
2421                        String "line"]), 99, [DangerWillRobinson],
2422    [],
2423    "modify a single partition on a block device",
2424    "\
2425 This runs L<sfdisk(8)> option to modify just the single
2426 partition C<n> (note: C<n> counts from 1).
2427
2428 For other parameters, see C<guestfs_sfdisk>.  You should usually
2429 pass C<0> for the cyls/heads/sectors parameters.
2430
2431 See also: C<guestfs_part_add>");
2432
2433   ("sfdisk_l", (RString "partitions", [Device "device"]), 100, [],
2434    [],
2435    "display the partition table",
2436    "\
2437 This displays the partition table on C<device>, in the
2438 human-readable output of the L<sfdisk(8)> command.  It is
2439 not intended to be parsed.
2440
2441 See also: C<guestfs_part_list>");
2442
2443   ("sfdisk_kernel_geometry", (RString "partitions", [Device "device"]), 101, [],
2444    [],
2445    "display the kernel geometry",
2446    "\
2447 This displays the kernel's idea of the geometry of C<device>.
2448
2449 The result is in human-readable format, and not designed to
2450 be parsed.");
2451
2452   ("sfdisk_disk_geometry", (RString "partitions", [Device "device"]), 102, [],
2453    [],
2454    "display the disk geometry from the partition table",
2455    "\
2456 This displays the disk geometry of C<device> read from the
2457 partition table.  Especially in the case where the underlying
2458 block device has been resized, this can be different from the
2459 kernel's idea of the geometry (see C<guestfs_sfdisk_kernel_geometry>).
2460
2461 The result is in human-readable format, and not designed to
2462 be parsed.");
2463
2464   ("vg_activate_all", (RErr, [Bool "activate"]), 103, [],
2465    [],
2466    "activate or deactivate all volume groups",
2467    "\
2468 This command activates or (if C<activate> is false) deactivates
2469 all logical volumes in all volume groups.
2470 If activated, then they are made known to the
2471 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2472 then those devices disappear.
2473
2474 This command is the same as running C<vgchange -a y|n>");
2475
2476   ("vg_activate", (RErr, [Bool "activate"; StringList "volgroups"]), 104, [],
2477    [],
2478    "activate or deactivate some volume groups",
2479    "\
2480 This command activates or (if C<activate> is false) deactivates
2481 all logical volumes in the listed volume groups C<volgroups>.
2482 If activated, then they are made known to the
2483 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2484 then those devices disappear.
2485
2486 This command is the same as running C<vgchange -a y|n volgroups...>
2487
2488 Note that if C<volgroups> is an empty list then B<all> volume groups
2489 are activated or deactivated.");
2490
2491   ("lvresize", (RErr, [Device "device"; Int "mbytes"]), 105, [],
2492    [InitNone, Always, TestOutput (
2493       [["part_disk"; "/dev/sda"; "mbr"];
2494        ["pvcreate"; "/dev/sda1"];
2495        ["vgcreate"; "VG"; "/dev/sda1"];
2496        ["lvcreate"; "LV"; "VG"; "10"];
2497        ["mkfs"; "ext2"; "/dev/VG/LV"];
2498        ["mount"; "/dev/VG/LV"; "/"];
2499        ["write_file"; "/new"; "test content"; "0"];
2500        ["umount"; "/"];
2501        ["lvresize"; "/dev/VG/LV"; "20"];
2502        ["e2fsck_f"; "/dev/VG/LV"];
2503        ["resize2fs"; "/dev/VG/LV"];
2504        ["mount"; "/dev/VG/LV"; "/"];
2505        ["cat"; "/new"]], "test content")],
2506    "resize an LVM logical volume",
2507    "\
2508 This resizes (expands or shrinks) an existing LVM logical
2509 volume to C<mbytes>.  When reducing, data in the reduced part
2510 is lost.");
2511
2512   ("resize2fs", (RErr, [Device "device"]), 106, [],
2513    [], (* lvresize tests this *)
2514    "resize an ext2/ext3 filesystem",
2515    "\
2516 This resizes an ext2 or ext3 filesystem to match the size of
2517 the underlying device.
2518
2519 I<Note:> It is sometimes required that you run C<guestfs_e2fsck_f>
2520 on the C<device> before calling this command.  For unknown reasons
2521 C<resize2fs> sometimes gives an error about this and sometimes not.
2522 In any case, it is always safe to call C<guestfs_e2fsck_f> before
2523 calling this function.");
2524
2525   ("find", (RStringList "names", [Pathname "directory"]), 107, [ProtocolLimitWarning],
2526    [InitBasicFS, Always, TestOutputList (
2527       [["find"; "/"]], ["lost+found"]);
2528     InitBasicFS, Always, TestOutputList (
2529       [["touch"; "/a"];
2530        ["mkdir"; "/b"];
2531        ["touch"; "/b/c"];
2532        ["find"; "/"]], ["a"; "b"; "b/c"; "lost+found"]);
2533     InitBasicFS, Always, TestOutputList (
2534       [["mkdir_p"; "/a/b/c"];
2535        ["touch"; "/a/b/c/d"];
2536        ["find"; "/a/b/"]], ["c"; "c/d"])],
2537    "find all files and directories",
2538    "\
2539 This command lists out all files and directories, recursively,
2540 starting at C<directory>.  It is essentially equivalent to
2541 running the shell command C<find directory -print> but some
2542 post-processing happens on the output, described below.
2543
2544 This returns a list of strings I<without any prefix>.  Thus
2545 if the directory structure was:
2546
2547  /tmp/a
2548  /tmp/b
2549  /tmp/c/d
2550
2551 then the returned list from C<guestfs_find> C</tmp> would be
2552 4 elements:
2553
2554  a
2555  b
2556  c
2557  c/d
2558
2559 If C<directory> is not a directory, then this command returns
2560 an error.
2561
2562 The returned list is sorted.
2563
2564 See also C<guestfs_find0>.");
2565
2566   ("e2fsck_f", (RErr, [Device "device"]), 108, [],
2567    [], (* lvresize tests this *)
2568    "check an ext2/ext3 filesystem",
2569    "\
2570 This runs C<e2fsck -p -f device>, ie. runs the ext2/ext3
2571 filesystem checker on C<device>, noninteractively (C<-p>),
2572 even if the filesystem appears to be clean (C<-f>).
2573
2574 This command is only needed because of C<guestfs_resize2fs>
2575 (q.v.).  Normally you should use C<guestfs_fsck>.");
2576
2577   ("sleep", (RErr, [Int "secs"]), 109, [],
2578    [InitNone, Always, TestRun (
2579       [["sleep"; "1"]])],
2580    "sleep for some seconds",
2581    "\
2582 Sleep for C<secs> seconds.");
2583
2584   ("ntfs_3g_probe", (RInt "status", [Bool "rw"; Device "device"]), 110, [],
2585    [InitNone, Always, TestOutputInt (
2586       [["part_disk"; "/dev/sda"; "mbr"];
2587        ["mkfs"; "ntfs"; "/dev/sda1"];
2588        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 0);
2589     InitNone, Always, TestOutputInt (
2590       [["part_disk"; "/dev/sda"; "mbr"];
2591        ["mkfs"; "ext2"; "/dev/sda1"];
2592        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 12)],
2593    "probe NTFS volume",
2594    "\
2595 This command runs the L<ntfs-3g.probe(8)> command which probes
2596 an NTFS C<device> for mountability.  (Not all NTFS volumes can
2597 be mounted read-write, and some cannot be mounted at all).
2598
2599 C<rw> is a boolean flag.  Set it to true if you want to test
2600 if the volume can be mounted read-write.  Set it to false if
2601 you want to test if the volume can be mounted read-only.
2602
2603 The return value is an integer which C<0> if the operation
2604 would succeed, or some non-zero value documented in the
2605 L<ntfs-3g.probe(8)> manual page.");
2606
2607   ("sh", (RString "output", [String "command"]), 111, [],
2608    [], (* XXX needs tests *)
2609    "run a command via the shell",
2610    "\
2611 This call runs a command from the guest filesystem via the
2612 guest's C</bin/sh>.
2613
2614 This is like C<guestfs_command>, but passes the command to:
2615
2616  /bin/sh -c \"command\"
2617
2618 Depending on the guest's shell, this usually results in
2619 wildcards being expanded, shell expressions being interpolated
2620 and so on.
2621
2622 All the provisos about C<guestfs_command> apply to this call.");
2623
2624   ("sh_lines", (RStringList "lines", [String "command"]), 112, [],
2625    [], (* XXX needs tests *)
2626    "run a command via the shell returning lines",
2627    "\
2628 This is the same as C<guestfs_sh>, but splits the result
2629 into a list of lines.
2630
2631 See also: C<guestfs_command_lines>");
2632
2633   ("glob_expand", (RStringList "paths", [Pathname "pattern"]), 113, [],
2634    (* Use Pathname here, and hence ABS_PATH (pattern,... in generated
2635     * code in stubs.c, since all valid glob patterns must start with "/".
2636     * There is no concept of "cwd" in libguestfs, hence no "."-relative names.
2637     *)
2638    [InitBasicFS, Always, TestOutputList (
2639       [["mkdir_p"; "/a/b/c"];
2640        ["touch"; "/a/b/c/d"];
2641        ["touch"; "/a/b/c/e"];
2642        ["glob_expand"; "/a/b/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2643     InitBasicFS, Always, TestOutputList (
2644       [["mkdir_p"; "/a/b/c"];
2645        ["touch"; "/a/b/c/d"];
2646        ["touch"; "/a/b/c/e"];
2647        ["glob_expand"; "/a/*/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2648     InitBasicFS, Always, TestOutputList (
2649       [["mkdir_p"; "/a/b/c"];
2650        ["touch"; "/a/b/c/d"];
2651        ["touch"; "/a/b/c/e"];
2652        ["glob_expand"; "/a/*/x/*"]], [])],
2653    "expand a wildcard path",
2654    "\
2655 This command searches for all the pathnames matching
2656 C<pattern> according to the wildcard expansion rules
2657 used by the shell.
2658
2659 If no paths match, then this returns an empty list
2660 (note: not an error).
2661
2662 It is just a wrapper around the C L<glob(3)> function
2663 with flags C<GLOB_MARK|GLOB_BRACE>.
2664 See that manual page for more details.");
2665
2666   ("scrub_device", (RErr, [Device "device"]), 114, [DangerWillRobinson],
2667    [InitNone, Always, TestRun ( (* use /dev/sdc because it's smaller *)
2668       [["scrub_device"; "/dev/sdc"]])],
2669    "scrub (securely wipe) a device",
2670    "\
2671 This command writes patterns over C<device> to make data retrieval
2672 more difficult.
2673
2674 It is an interface to the L<scrub(1)> program.  See that
2675 manual page for more details.");
2676
2677   ("scrub_file", (RErr, [Pathname "file"]), 115, [],
2678    [InitBasicFS, Always, TestRun (
2679       [["write_file"; "/file"; "content"; "0"];
2680        ["scrub_file"; "/file"]])],
2681    "scrub (securely wipe) a file",
2682    "\
2683 This command writes patterns over a file to make data retrieval
2684 more difficult.
2685
2686 The file is I<removed> after scrubbing.
2687
2688 It is an interface to the L<scrub(1)> program.  See that
2689 manual page for more details.");
2690
2691   ("scrub_freespace", (RErr, [Pathname "dir"]), 116, [],
2692    [], (* XXX needs testing *)
2693    "scrub (securely wipe) free space",
2694    "\
2695 This command creates the directory C<dir> and then fills it
2696 with files until the filesystem is full, and scrubs the files
2697 as for C<guestfs_scrub_file>, and deletes them.
2698 The intention is to scrub any free space on the partition
2699 containing C<dir>.
2700
2701 It is an interface to the L<scrub(1)> program.  See that
2702 manual page for more details.");
2703
2704   ("mkdtemp", (RString "dir", [Pathname "template"]), 117, [],
2705    [InitBasicFS, Always, TestRun (
2706       [["mkdir"; "/tmp"];
2707        ["mkdtemp"; "/tmp/tmpXXXXXX"]])],
2708    "create a temporary directory",
2709    "\
2710 This command creates a temporary directory.  The
2711 C<template> parameter should be a full pathname for the
2712 temporary directory name with the final six characters being
2713 \"XXXXXX\".
2714
2715 For example: \"/tmp/myprogXXXXXX\" or \"/Temp/myprogXXXXXX\",
2716 the second one being suitable for Windows filesystems.
2717
2718 The name of the temporary directory that was created
2719 is returned.
2720
2721 The temporary directory is created with mode 0700
2722 and is owned by root.
2723
2724 The caller is responsible for deleting the temporary
2725 directory and its contents after use.
2726
2727 See also: L<mkdtemp(3)>");
2728
2729   ("wc_l", (RInt "lines", [Pathname "path"]), 118, [],
2730    [InitISOFS, Always, TestOutputInt (
2731       [["wc_l"; "/10klines"]], 10000)],
2732    "count lines in a file",
2733    "\
2734 This command counts the lines in a file, using the
2735 C<wc -l> external command.");
2736
2737   ("wc_w", (RInt "words", [Pathname "path"]), 119, [],
2738    [InitISOFS, Always, TestOutputInt (
2739       [["wc_w"; "/10klines"]], 10000)],
2740    "count words in a file",
2741    "\
2742 This command counts the words in a file, using the
2743 C<wc -w> external command.");
2744
2745   ("wc_c", (RInt "chars", [Pathname "path"]), 120, [],
2746    [InitISOFS, Always, TestOutputInt (
2747       [["wc_c"; "/100kallspaces"]], 102400)],
2748    "count characters in a file",
2749    "\
2750 This command counts the characters in a file, using the
2751 C<wc -c> external command.");
2752
2753   ("head", (RStringList "lines", [Pathname "path"]), 121, [ProtocolLimitWarning],
2754    [InitISOFS, Always, TestOutputList (
2755       [["head"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"])],
2756    "return first 10 lines of a file",
2757    "\
2758 This command returns up to the first 10 lines of a file as
2759 a list of strings.");
2760
2761   ("head_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 122, [ProtocolLimitWarning],
2762    [InitISOFS, Always, TestOutputList (
2763       [["head_n"; "3"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2764     InitISOFS, Always, TestOutputList (
2765       [["head_n"; "-9997"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2766     InitISOFS, Always, TestOutputList (
2767       [["head_n"; "0"; "/10klines"]], [])],
2768    "return first N lines of a file",
2769    "\
2770 If the parameter C<nrlines> is a positive number, this returns the first
2771 C<nrlines> lines of the file C<path>.
2772
2773 If the parameter C<nrlines> is a negative number, this returns lines
2774 from the file C<path>, excluding the last C<nrlines> lines.
2775
2776 If the parameter C<nrlines> is zero, this returns an empty list.");
2777
2778   ("tail", (RStringList "lines", [Pathname "path"]), 123, [ProtocolLimitWarning],
2779    [InitISOFS, Always, TestOutputList (
2780       [["tail"; "/10klines"]], ["9990abcdefghijklmnopqrstuvwxyz";"9991abcdefghijklmnopqrstuvwxyz";"9992abcdefghijklmnopqrstuvwxyz";"9993abcdefghijklmnopqrstuvwxyz";"9994abcdefghijklmnopqrstuvwxyz";"9995abcdefghijklmnopqrstuvwxyz";"9996abcdefghijklmnopqrstuvwxyz";"9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"])],
2781    "return last 10 lines of a file",
2782    "\
2783 This command returns up to the last 10 lines of a file as
2784 a list of strings.");
2785
2786   ("tail_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 124, [ProtocolLimitWarning],
2787    [InitISOFS, Always, TestOutputList (
2788       [["tail_n"; "3"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2789     InitISOFS, Always, TestOutputList (
2790       [["tail_n"; "-9998"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2791     InitISOFS, Always, TestOutputList (
2792       [["tail_n"; "0"; "/10klines"]], [])],
2793    "return last N lines of a file",
2794    "\
2795 If the parameter C<nrlines> is a positive number, this returns the last
2796 C<nrlines> lines of the file C<path>.
2797
2798 If the parameter C<nrlines> is a negative number, this returns lines
2799 from the file C<path>, starting with the C<-nrlines>th line.
2800
2801 If the parameter C<nrlines> is zero, this returns an empty list.");
2802
2803   ("df", (RString "output", []), 125, [],
2804    [], (* XXX Tricky to test because it depends on the exact format
2805         * of the 'df' command and other imponderables.
2806         *)
2807    "report file system disk space usage",
2808    "\
2809 This command runs the C<df> command to report disk space used.
2810
2811 This command is mostly useful for interactive sessions.  It
2812 is I<not> intended that you try to parse the output string.
2813 Use C<statvfs> from programs.");
2814
2815   ("df_h", (RString "output", []), 126, [],
2816    [], (* XXX Tricky to test because it depends on the exact format
2817         * of the 'df' command and other imponderables.
2818         *)
2819    "report file system disk space usage (human readable)",
2820    "\
2821 This command runs the C<df -h> command to report disk space used
2822 in human-readable format.
2823
2824 This command is mostly useful for interactive sessions.  It
2825 is I<not> intended that you try to parse the output string.
2826 Use C<statvfs> from programs.");
2827
2828   ("du", (RInt64 "sizekb", [Pathname "path"]), 127, [],
2829    [InitISOFS, Always, TestOutputInt (
2830       [["du"; "/directory"]], 2 (* ISO fs blocksize is 2K *))],
2831    "estimate file space usage",
2832    "\
2833 This command runs the C<du -s> command to estimate file space
2834 usage for C<path>.
2835
2836 C<path> can be a file or a directory.  If C<path> is a directory
2837 then the estimate includes the contents of the directory and all
2838 subdirectories (recursively).
2839
2840 The result is the estimated size in I<kilobytes>
2841 (ie. units of 1024 bytes).");
2842
2843   ("initrd_list", (RStringList "filenames", [Pathname "path"]), 128, [],
2844    [InitISOFS, Always, TestOutputList (
2845       [["initrd_list"; "/initrd"]], ["empty";"known-1";"known-2";"known-3";"known-4"; "known-5"])],
2846    "list files in an initrd",
2847    "\
2848 This command lists out files contained in an initrd.
2849
2850 The files are listed without any initial C</> character.  The
2851 files are listed in the order they appear (not necessarily
2852 alphabetical).  Directory names are listed as separate items.
2853
2854 Old Linux kernels (2.4 and earlier) used a compressed ext2
2855 filesystem as initrd.  We I<only> support the newer initramfs
2856 format (compressed cpio files).");
2857
2858   ("mount_loop", (RErr, [Pathname "file"; Pathname "mountpoint"]), 129, [],
2859    [],
2860    "mount a file using the loop device",
2861    "\
2862 This command lets you mount C<file> (a filesystem image
2863 in a file) on a mount point.  It is entirely equivalent to
2864 the command C<mount -o loop file mountpoint>.");
2865
2866   ("mkswap", (RErr, [Device "device"]), 130, [],
2867    [InitEmpty, Always, TestRun (
2868       [["part_disk"; "/dev/sda"; "mbr"];
2869        ["mkswap"; "/dev/sda1"]])],
2870    "create a swap partition",
2871    "\
2872 Create a swap partition on C<device>.");
2873
2874   ("mkswap_L", (RErr, [String "label"; Device "device"]), 131, [],
2875    [InitEmpty, Always, TestRun (
2876       [["part_disk"; "/dev/sda"; "mbr"];
2877        ["mkswap_L"; "hello"; "/dev/sda1"]])],
2878    "create a swap partition with a label",
2879    "\
2880 Create a swap partition on C<device> with label C<label>.
2881
2882 Note that you cannot attach a swap label to a block device
2883 (eg. C</dev/sda>), just to a partition.  This appears to be
2884 a limitation of the kernel or swap tools.");
2885
2886   ("mkswap_U", (RErr, [String "uuid"; Device "device"]), 132, [],
2887    (let uuid = uuidgen () in
2888     [InitEmpty, Always, TestRun (
2889        [["part_disk"; "/dev/sda"; "mbr"];
2890         ["mkswap_U"; uuid; "/dev/sda1"]])]),
2891    "create a swap partition with an explicit UUID",
2892    "\
2893 Create a swap partition on C<device> with UUID C<uuid>.");
2894
2895   ("mknod", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 133, [],
2896    [InitBasicFS, Always, TestOutputStruct (
2897       [["mknod"; "0o10777"; "0"; "0"; "/node"];
2898        (* NB: default umask 022 means 0777 -> 0755 in these tests *)
2899        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)]);
2900     InitBasicFS, Always, TestOutputStruct (
2901       [["mknod"; "0o60777"; "66"; "99"; "/node"];
2902        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
2903    "make block, character or FIFO devices",
2904    "\
2905 This call creates block or character special devices, or
2906 named pipes (FIFOs).
2907
2908 The C<mode> parameter should be the mode, using the standard
2909 constants.  C<devmajor> and C<devminor> are the
2910 device major and minor numbers, only used when creating block
2911 and character special devices.");
2912
2913   ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [],
2914    [InitBasicFS, Always, TestOutputStruct (
2915       [["mkfifo"; "0o777"; "/node"];
2916        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)])],
2917    "make FIFO (named pipe)",
2918    "\
2919 This call creates a FIFO (named pipe) called C<path> with
2920 mode C<mode>.  It is just a convenient wrapper around
2921 C<guestfs_mknod>.");
2922
2923   ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [],
2924    [InitBasicFS, Always, TestOutputStruct (
2925       [["mknod_b"; "0o777"; "99"; "66"; "/node"];
2926        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
2927    "make block device node",
2928    "\
2929 This call creates a block device node called C<path> with
2930 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
2931 It is just a convenient wrapper around C<guestfs_mknod>.");
2932
2933   ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [],
2934    [InitBasicFS, Always, TestOutputStruct (
2935       [["mknod_c"; "0o777"; "99"; "66"; "/node"];
2936        ["stat"; "/node"]], [CompareWithInt ("mode", 0o20755)])],
2937    "make char device node",
2938    "\
2939 This call creates a char device node called C<path> with
2940 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
2941 It is just a convenient wrapper around C<guestfs_mknod>.");
2942
2943   ("umask", (RInt "oldmask", [Int "mask"]), 137, [],
2944    [], (* XXX umask is one of those stateful things that we should
2945         * reset between each test.
2946         *)
2947    "set file mode creation mask (umask)",
2948    "\
2949 This function sets the mask used for creating new files and
2950 device nodes to C<mask & 0777>.
2951
2952 Typical umask values would be C<022> which creates new files
2953 with permissions like \"-rw-r--r--\" or \"-rwxr-xr-x\", and
2954 C<002> which creates new files with permissions like
2955 \"-rw-rw-r--\" or \"-rwxrwxr-x\".
2956
2957 The default umask is C<022>.  This is important because it
2958 means that directories and device nodes will be created with
2959 C<0644> or C<0755> mode even if you specify C<0777>.
2960
2961 See also L<umask(2)>, C<guestfs_mknod>, C<guestfs_mkdir>.
2962
2963 This call returns the previous umask.");
2964
2965   ("readdir", (RStructList ("entries", "dirent"), [Pathname "dir"]), 138, [],
2966    [],
2967    "read directories entries",
2968    "\
2969 This returns the list of directory entries in directory C<dir>.
2970
2971 All entries in the directory are returned, including C<.> and
2972 C<..>.  The entries are I<not> sorted, but returned in the same
2973 order as the underlying filesystem.
2974
2975 Also this call returns basic file type information about each
2976 file.  The C<ftyp> field will contain one of the following characters:
2977
2978 =over 4
2979
2980 =item 'b'
2981
2982 Block special
2983
2984 =item 'c'
2985
2986 Char special
2987
2988 =item 'd'
2989
2990 Directory
2991
2992 =item 'f'
2993
2994 FIFO (named pipe)
2995
2996 =item 'l'
2997
2998 Symbolic link
2999
3000 =item 'r'
3001
3002 Regular file
3003
3004 =item 's'
3005
3006 Socket
3007
3008 =item 'u'
3009
3010 Unknown file type
3011
3012 =item '?'
3013
3014 The L<readdir(3)> returned a C<d_type> field with an
3015 unexpected value
3016
3017 =back
3018
3019 This function is primarily intended for use by programs.  To
3020 get a simple list of names, use C<guestfs_ls>.  To get a printable
3021 directory for human consumption, use C<guestfs_ll>.");
3022
3023   ("sfdiskM", (RErr, [Device "device"; StringList "lines"]), 139, [DangerWillRobinson],
3024    [],
3025    "create partitions on a block device",
3026    "\
3027 This is a simplified interface to the C<guestfs_sfdisk>
3028 command, where partition sizes are specified in megabytes
3029 only (rounded to the nearest cylinder) and you don't need
3030 to specify the cyls, heads and sectors parameters which
3031 were rarely if ever used anyway.
3032
3033 See also: C<guestfs_sfdisk>, the L<sfdisk(8)> manpage
3034 and C<guestfs_part_disk>");
3035
3036   ("zfile", (RString "description", [String "meth"; Pathname "path"]), 140, [DeprecatedBy "file"],
3037    [],
3038    "determine file type inside a compressed file",
3039    "\
3040 This command runs C<file> after first decompressing C<path>
3041 using C<method>.
3042
3043 C<method> must be one of C<gzip>, C<compress> or C<bzip2>.
3044
3045 Since 1.0.63, use C<guestfs_file> instead which can now
3046 process compressed files.");
3047
3048   ("getxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 141, [],
3049    [],
3050    "list extended attributes of a file or directory",
3051    "\
3052 This call lists the extended attributes of the file or directory
3053 C<path>.
3054
3055 At the system call level, this is a combination of the
3056 L<listxattr(2)> and L<getxattr(2)> calls.
3057
3058 See also: C<guestfs_lgetxattrs>, L<attr(5)>.");
3059
3060   ("lgetxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 142, [],
3061    [],
3062    "list extended attributes of a file or directory",
3063    "\
3064 This is the same as C<guestfs_getxattrs>, but if C<path>
3065 is a symbolic link, then it returns the extended attributes
3066 of the link itself.");
3067
3068   ("setxattr", (RErr, [String "xattr";
3069                        String "val"; Int "vallen"; (* will be BufferIn *)
3070                        Pathname "path"]), 143, [],
3071    [],
3072    "set extended attribute of a file or directory",
3073    "\
3074 This call sets the extended attribute named C<xattr>
3075 of the file C<path> to the value C<val> (of length C<vallen>).
3076 The value is arbitrary 8 bit data.
3077
3078 See also: C<guestfs_lsetxattr>, L<attr(5)>.");
3079
3080   ("lsetxattr", (RErr, [String "xattr";
3081                         String "val"; Int "vallen"; (* will be BufferIn *)
3082                         Pathname "path"]), 144, [],
3083    [],
3084    "set extended attribute of a file or directory",
3085    "\
3086 This is the same as C<guestfs_setxattr>, but if C<path>
3087 is a symbolic link, then it sets an extended attribute
3088 of the link itself.");
3089
3090   ("removexattr", (RErr, [String "xattr"; Pathname "path"]), 145, [],
3091    [],
3092    "remove extended attribute of a file or directory",
3093    "\
3094 This call removes the extended attribute named C<xattr>
3095 of the file C<path>.
3096
3097 See also: C<guestfs_lremovexattr>, L<attr(5)>.");
3098
3099   ("lremovexattr", (RErr, [String "xattr"; Pathname "path"]), 146, [],
3100    [],
3101    "remove extended attribute of a file or directory",
3102    "\
3103 This is the same as C<guestfs_removexattr>, but if C<path>
3104 is a symbolic link, then it removes an extended attribute
3105 of the link itself.");
3106
3107   ("mountpoints", (RHashtable "mps", []), 147, [],
3108    [],
3109    "show mountpoints",
3110    "\
3111 This call is similar to C<guestfs_mounts>.  That call returns
3112 a list of devices.  This one returns a hash table (map) of
3113 device name to directory where the device is mounted.");
3114
3115   ("mkmountpoint", (RErr, [String "exemptpath"]), 148, [],
3116   (* This is a special case: while you would expect a parameter
3117    * of type "Pathname", that doesn't work, because it implies
3118    * NEED_ROOT in the generated calling code in stubs.c, and
3119    * this function cannot use NEED_ROOT.
3120    *)
3121    [],
3122    "create a mountpoint",
3123    "\
3124 C<guestfs_mkmountpoint> and C<guestfs_rmmountpoint> are
3125 specialized calls that can be used to create extra mountpoints
3126 before mounting the first filesystem.
3127
3128 These calls are I<only> necessary in some very limited circumstances,
3129 mainly the case where you want to mount a mix of unrelated and/or
3130 read-only filesystems together.
3131
3132 For example, live CDs often contain a \"Russian doll\" nest of
3133 filesystems, an ISO outer layer, with a squashfs image inside, with
3134 an ext2/3 image inside that.  You can unpack this as follows
3135 in guestfish:
3136
3137  add-ro Fedora-11-i686-Live.iso
3138  run
3139  mkmountpoint /cd
3140  mkmountpoint /squash
3141  mkmountpoint /ext3
3142  mount /dev/sda /cd
3143  mount-loop /cd/LiveOS/squashfs.img /squash
3144  mount-loop /squash/LiveOS/ext3fs.img /ext3
3145
3146 The inner filesystem is now unpacked under the /ext3 mountpoint.");
3147
3148   ("rmmountpoint", (RErr, [String "exemptpath"]), 149, [],
3149    [],
3150    "remove a mountpoint",
3151    "\
3152 This calls removes a mountpoint that was previously created
3153 with C<guestfs_mkmountpoint>.  See C<guestfs_mkmountpoint>
3154 for full details.");
3155
3156   ("read_file", (RBufferOut "content", [Pathname "path"]), 150, [ProtocolLimitWarning],
3157    [InitISOFS, Always, TestOutputBuffer (
3158       [["read_file"; "/known-4"]], "abc\ndef\nghi")],
3159    "read a file",
3160    "\
3161 This calls returns the contents of the file C<path> as a
3162 buffer.
3163
3164 Unlike C<guestfs_cat>, this function can correctly
3165 handle files that contain embedded ASCII NUL characters.
3166 However unlike C<guestfs_download>, this function is limited
3167 in the total size of file that can be handled.");
3168
3169   ("grep", (RStringList "lines", [String "regex"; Pathname "path"]), 151, [ProtocolLimitWarning],
3170    [InitISOFS, Always, TestOutputList (
3171       [["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]);
3172     InitISOFS, Always, TestOutputList (
3173       [["grep"; "nomatch"; "/test-grep.txt"]], [])],
3174    "return lines matching a pattern",
3175    "\
3176 This calls the external C<grep> program and returns the
3177 matching lines.");
3178
3179   ("egrep", (RStringList "lines", [String "regex"; Pathname "path"]), 152, [ProtocolLimitWarning],
3180    [InitISOFS, Always, TestOutputList (
3181       [["egrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3182    "return lines matching a pattern",
3183    "\
3184 This calls the external C<egrep> program and returns the
3185 matching lines.");
3186
3187   ("fgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 153, [ProtocolLimitWarning],
3188    [InitISOFS, Always, TestOutputList (
3189       [["fgrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3190    "return lines matching a pattern",
3191    "\
3192 This calls the external C<fgrep> program and returns the
3193 matching lines.");
3194
3195   ("grepi", (RStringList "lines", [String "regex"; Pathname "path"]), 154, [ProtocolLimitWarning],
3196    [InitISOFS, Always, TestOutputList (
3197       [["grepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3198    "return lines matching a pattern",
3199    "\
3200 This calls the external C<grep -i> program and returns the
3201 matching lines.");
3202
3203   ("egrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 155, [ProtocolLimitWarning],
3204    [InitISOFS, Always, TestOutputList (
3205       [["egrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3206    "return lines matching a pattern",
3207    "\
3208 This calls the external C<egrep -i> program and returns the
3209 matching lines.");
3210
3211   ("fgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 156, [ProtocolLimitWarning],
3212    [InitISOFS, Always, TestOutputList (
3213       [["fgrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3214    "return lines matching a pattern",
3215    "\
3216 This calls the external C<fgrep -i> program and returns the
3217 matching lines.");
3218
3219   ("zgrep", (RStringList "lines", [String "regex"; Pathname "path"]), 157, [ProtocolLimitWarning],
3220    [InitISOFS, Always, TestOutputList (
3221       [["zgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3222    "return lines matching a pattern",
3223    "\
3224 This calls the external C<zgrep> program and returns the
3225 matching lines.");
3226
3227   ("zegrep", (RStringList "lines", [String "regex"; Pathname "path"]), 158, [ProtocolLimitWarning],
3228    [InitISOFS, Always, TestOutputList (
3229       [["zegrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3230    "return lines matching a pattern",
3231    "\
3232 This calls the external C<zegrep> program and returns the
3233 matching lines.");
3234
3235   ("zfgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 159, [ProtocolLimitWarning],
3236    [InitISOFS, Always, TestOutputList (
3237       [["zfgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3238    "return lines matching a pattern",
3239    "\
3240 This calls the external C<zfgrep> program and returns the
3241 matching lines.");
3242
3243   ("zgrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 160, [ProtocolLimitWarning],
3244    [InitISOFS, Always, TestOutputList (
3245       [["zgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3246    "return lines matching a pattern",
3247    "\
3248 This calls the external C<zgrep -i> program and returns the
3249 matching lines.");
3250
3251   ("zegrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 161, [ProtocolLimitWarning],
3252    [InitISOFS, Always, TestOutputList (
3253       [["zegrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3254    "return lines matching a pattern",
3255    "\
3256 This calls the external C<zegrep -i> program and returns the
3257 matching lines.");
3258
3259   ("zfgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 162, [ProtocolLimitWarning],
3260    [InitISOFS, Always, TestOutputList (
3261       [["zfgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3262    "return lines matching a pattern",
3263    "\
3264 This calls the external C<zfgrep -i> program and returns the
3265 matching lines.");
3266
3267   ("realpath", (RString "rpath", [Pathname "path"]), 163, [],
3268    [InitISOFS, Always, TestOutput (
3269       [["realpath"; "/../directory"]], "/directory")],
3270    "canonicalized absolute pathname",
3271    "\
3272 Return the canonicalized absolute pathname of C<path>.  The
3273 returned path has no C<.>, C<..> or symbolic link path elements.");
3274
3275   ("ln", (RErr, [String "target"; Pathname "linkname"]), 164, [],
3276    [InitBasicFS, Always, TestOutputStruct (
3277       [["touch"; "/a"];
3278        ["ln"; "/a"; "/b"];
3279        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3280    "create a hard link",
3281    "\
3282 This command creates a hard link using the C<ln> command.");
3283
3284   ("ln_f", (RErr, [String "target"; Pathname "linkname"]), 165, [],
3285    [InitBasicFS, Always, TestOutputStruct (
3286       [["touch"; "/a"];
3287        ["touch"; "/b"];
3288        ["ln_f"; "/a"; "/b"];
3289        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3290    "create a hard link",
3291    "\
3292 This command creates a hard link using the C<ln -f> command.
3293 The C<-f> option removes the link (C<linkname>) if it exists already.");
3294
3295   ("ln_s", (RErr, [String "target"; Pathname "linkname"]), 166, [],
3296    [InitBasicFS, Always, TestOutputStruct (
3297       [["touch"; "/a"];
3298        ["ln_s"; "a"; "/b"];
3299        ["lstat"; "/b"]], [CompareWithInt ("mode", 0o120777)])],
3300    "create a symbolic link",
3301    "\
3302 This command creates a symbolic link using the C<ln -s> command.");
3303
3304   ("ln_sf", (RErr, [String "target"; Pathname "linkname"]), 167, [],
3305    [InitBasicFS, Always, TestOutput (
3306       [["mkdir_p"; "/a/b"];
3307        ["touch"; "/a/b/c"];
3308        ["ln_sf"; "../d"; "/a/b/c"];
3309        ["readlink"; "/a/b/c"]], "../d")],
3310    "create a symbolic link",
3311    "\
3312 This command creates a symbolic link using the C<ln -sf> command,
3313 The C<-f> option removes the link (C<linkname>) if it exists already.");
3314
3315   ("readlink", (RString "link", [Pathname "path"]), 168, [],
3316    [] (* XXX tested above *),
3317    "read the target of a symbolic link",
3318    "\
3319 This command reads the target of a symbolic link.");
3320
3321   ("fallocate", (RErr, [Pathname "path"; Int "len"]), 169, [],
3322    [InitBasicFS, Always, TestOutputStruct (
3323       [["fallocate"; "/a"; "1000000"];
3324        ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
3325    "preallocate a file in the guest filesystem",
3326    "\
3327 This command preallocates a file (containing zero bytes) named
3328 C<path> of size C<len> bytes.  If the file exists already, it
3329 is overwritten.
3330
3331 Do not confuse this with the guestfish-specific
3332 C<alloc> command which allocates a file in the host and
3333 attaches it as a device.");
3334
3335   ("swapon_device", (RErr, [Device "device"]), 170, [],
3336    [InitPartition, Always, TestRun (
3337       [["mkswap"; "/dev/sda1"];
3338        ["swapon_device"; "/dev/sda1"];
3339        ["swapoff_device"; "/dev/sda1"]])],
3340    "enable swap on device",
3341    "\
3342 This command enables the libguestfs appliance to use the
3343 swap device or partition named C<device>.  The increased
3344 memory is made available for all commands, for example
3345 those run using C<guestfs_command> or C<guestfs_sh>.
3346
3347 Note that you should not swap to existing guest swap
3348 partitions unless you know what you are doing.  They may
3349 contain hibernation information, or other information that
3350 the guest doesn't want you to trash.  You also risk leaking
3351 information about the host to the guest this way.  Instead,
3352 attach a new host device to the guest and swap on that.");
3353
3354   ("swapoff_device", (RErr, [Device "device"]), 171, [],
3355    [], (* XXX tested by swapon_device *)
3356    "disable swap on device",
3357    "\
3358 This command disables the libguestfs appliance swap
3359 device or partition named C<device>.
3360 See C<guestfs_swapon_device>.");
3361
3362   ("swapon_file", (RErr, [Pathname "file"]), 172, [],
3363    [InitBasicFS, Always, TestRun (
3364       [["fallocate"; "/swap"; "8388608"];
3365        ["mkswap_file"; "/swap"];
3366        ["swapon_file"; "/swap"];
3367        ["swapoff_file"; "/swap"]])],
3368    "enable swap on file",
3369    "\
3370 This command enables swap to a file.
3371 See C<guestfs_swapon_device> for other notes.");
3372
3373   ("swapoff_file", (RErr, [Pathname "file"]), 173, [],
3374    [], (* XXX tested by swapon_file *)
3375    "disable swap on file",
3376    "\
3377 This command disables the libguestfs appliance swap on file.");
3378
3379   ("swapon_label", (RErr, [String "label"]), 174, [],
3380    [InitEmpty, Always, TestRun (
3381       [["part_disk"; "/dev/sdb"; "mbr"];
3382        ["mkswap_L"; "swapit"; "/dev/sdb1"];
3383        ["swapon_label"; "swapit"];
3384        ["swapoff_label"; "swapit"];
3385        ["zero"; "/dev/sdb"];
3386        ["blockdev_rereadpt"; "/dev/sdb"]])],
3387    "enable swap on labeled swap partition",
3388    "\
3389 This command enables swap to a labeled swap partition.
3390 See C<guestfs_swapon_device> for other notes.");
3391
3392   ("swapoff_label", (RErr, [String "label"]), 175, [],
3393    [], (* XXX tested by swapon_label *)
3394    "disable swap on labeled swap partition",
3395    "\
3396 This command disables the libguestfs appliance swap on
3397 labeled swap partition.");
3398
3399   ("swapon_uuid", (RErr, [String "uuid"]), 176, [],
3400    (let uuid = uuidgen () in
3401     [InitEmpty, Always, TestRun (
3402        [["mkswap_U"; uuid; "/dev/sdb"];
3403         ["swapon_uuid"; uuid];
3404         ["swapoff_uuid"; uuid]])]),
3405    "enable swap on swap partition by UUID",
3406    "\
3407 This command enables swap to a swap partition with the given UUID.
3408 See C<guestfs_swapon_device> for other notes.");
3409
3410   ("swapoff_uuid", (RErr, [String "uuid"]), 177, [],
3411    [], (* XXX tested by swapon_uuid *)
3412    "disable swap on swap partition by UUID",
3413    "\
3414 This command disables the libguestfs appliance swap partition
3415 with the given UUID.");
3416
3417   ("mkswap_file", (RErr, [Pathname "path"]), 178, [],
3418    [InitBasicFS, Always, TestRun (
3419       [["fallocate"; "/swap"; "8388608"];
3420        ["mkswap_file"; "/swap"]])],
3421    "create a swap file",
3422    "\
3423 Create a swap file.
3424
3425 This command just writes a swap file signature to an existing
3426 file.  To create the file itself, use something like C<guestfs_fallocate>.");
3427
3428   ("inotify_init", (RErr, [Int "maxevents"]), 179, [],
3429    [InitISOFS, Always, TestRun (
3430       [["inotify_init"; "0"]])],
3431    "create an inotify handle",
3432    "\
3433 This command creates a new inotify handle.
3434 The inotify subsystem can be used to notify events which happen to
3435 objects in the guest filesystem.
3436
3437 C<maxevents> is the maximum number of events which will be
3438 queued up between calls to C<guestfs_inotify_read> or
3439 C<guestfs_inotify_files>.
3440 If this is passed as C<0>, then the kernel (or previously set)
3441 default is used.  For Linux 2.6.29 the default was 16384 events.
3442 Beyond this limit, the kernel throws away events, but records
3443 the fact that it threw them away by setting a flag
3444 C<IN_Q_OVERFLOW> in the returned structure list (see
3445 C<guestfs_inotify_read>).
3446
3447 Before any events are generated, you have to add some
3448 watches to the internal watch list.  See:
3449 C<guestfs_inotify_add_watch>,
3450 C<guestfs_inotify_rm_watch> and
3451 C<guestfs_inotify_watch_all>.
3452
3453 Queued up events should be read periodically by calling
3454 C<guestfs_inotify_read>
3455 (or C<guestfs_inotify_files> which is just a helpful
3456 wrapper around C<guestfs_inotify_read>).  If you don't
3457 read the events out often enough then you risk the internal
3458 queue overflowing.
3459
3460 The handle should be closed after use by calling
3461 C<guestfs_inotify_close>.  This also removes any
3462 watches automatically.
3463
3464 See also L<inotify(7)> for an overview of the inotify interface
3465 as exposed by the Linux kernel, which is roughly what we expose
3466 via libguestfs.  Note that there is one global inotify handle
3467 per libguestfs instance.");
3468
3469   ("inotify_add_watch", (RInt64 "wd", [Pathname "path"; Int "mask"]), 180, [],
3470    [InitBasicFS, Always, TestOutputList (
3471       [["inotify_init"; "0"];
3472        ["inotify_add_watch"; "/"; "1073741823"];
3473        ["touch"; "/a"];
3474        ["touch"; "/b"];
3475        ["inotify_files"]], ["a"; "b"])],
3476    "add an inotify watch",
3477    "\
3478 Watch C<path> for the events listed in C<mask>.
3479
3480 Note that if C<path> is a directory then events within that
3481 directory are watched, but this does I<not> happen recursively
3482 (in subdirectories).
3483
3484 Note for non-C or non-Linux callers: the inotify events are
3485 defined by the Linux kernel ABI and are listed in
3486 C</usr/include/sys/inotify.h>.");
3487
3488   ("inotify_rm_watch", (RErr, [Int(*XXX64*) "wd"]), 181, [],
3489    [],
3490    "remove an inotify watch",
3491    "\
3492 Remove a previously defined inotify watch.
3493 See C<guestfs_inotify_add_watch>.");
3494
3495   ("inotify_read", (RStructList ("events", "inotify_event"), []), 182, [],
3496    [],
3497    "return list of inotify events",
3498    "\
3499 Return the complete queue of events that have happened
3500 since the previous read call.
3501
3502 If no events have happened, this returns an empty list.
3503
3504 I<Note>: In order to make sure that all events have been
3505 read, you must call this function repeatedly until it
3506 returns an empty list.  The reason is that the call will
3507 read events up to the maximum appliance-to-host message
3508 size and leave remaining events in the queue.");
3509
3510   ("inotify_files", (RStringList "paths", []), 183, [],
3511    [],
3512    "return list of watched files that had events",
3513    "\
3514 This function is a helpful wrapper around C<guestfs_inotify_read>
3515 which just returns a list of pathnames of objects that were
3516 touched.  The returned pathnames are sorted and deduplicated.");
3517
3518   ("inotify_close", (RErr, []), 184, [],
3519    [],
3520    "close the inotify handle",
3521    "\
3522 This closes the inotify handle which was previously
3523 opened by inotify_init.  It removes all watches, throws
3524 away any pending events, and deallocates all resources.");
3525
3526   ("setcon", (RErr, [String "context"]), 185, [],
3527    [],
3528    "set SELinux security context",
3529    "\
3530 This sets the SELinux security context of the daemon
3531 to the string C<context>.
3532
3533 See the documentation about SELINUX in L<guestfs(3)>.");
3534
3535   ("getcon", (RString "context", []), 186, [],
3536    [],
3537    "get SELinux security context",
3538    "\
3539 This gets the SELinux security context of the daemon.
3540
3541 See the documentation about SELINUX in L<guestfs(3)>,
3542 and C<guestfs_setcon>");
3543
3544   ("mkfs_b", (RErr, [String "fstype"; Int "blocksize"; Device "device"]), 187, [],
3545    [InitEmpty, Always, TestOutput (
3546       [["part_disk"; "/dev/sda"; "mbr"];
3547        ["mkfs_b"; "ext2"; "4096"; "/dev/sda1"];
3548        ["mount"; "/dev/sda1"; "/"];
3549        ["write_file"; "/new"; "new file contents"; "0"];
3550        ["cat"; "/new"]], "new file contents")],
3551    "make a filesystem with block size",
3552    "\
3553 This call is similar to C<guestfs_mkfs>, but it allows you to
3554 control the block size of the resulting filesystem.  Supported
3555 block sizes depend on the filesystem type, but typically they
3556 are C<1024>, C<2048> or C<4096> only.");
3557
3558   ("mke2journal", (RErr, [Int "blocksize"; Device "device"]), 188, [],
3559    [InitEmpty, Always, TestOutput (
3560       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3561        ["mke2journal"; "4096"; "/dev/sda1"];
3562        ["mke2fs_J"; "ext2"; "4096"; "/dev/sda2"; "/dev/sda1"];
3563        ["mount"; "/dev/sda2"; "/"];
3564        ["write_file"; "/new"; "new file contents"; "0"];
3565        ["cat"; "/new"]], "new file contents")],
3566    "make ext2/3/4 external journal",
3567    "\
3568 This creates an ext2 external journal on C<device>.  It is equivalent
3569 to the command:
3570
3571  mke2fs -O journal_dev -b blocksize device");
3572
3573   ("mke2journal_L", (RErr, [Int "blocksize"; String "label"; Device "device"]), 189, [],
3574    [InitEmpty, Always, TestOutput (
3575       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3576        ["mke2journal_L"; "4096"; "JOURNAL"; "/dev/sda1"];
3577        ["mke2fs_JL"; "ext2"; "4096"; "/dev/sda2"; "JOURNAL"];
3578        ["mount"; "/dev/sda2"; "/"];
3579        ["write_file"; "/new"; "new file contents"; "0"];
3580        ["cat"; "/new"]], "new file contents")],
3581    "make ext2/3/4 external journal with label",
3582    "\
3583 This creates an ext2 external journal on C<device> with label C<label>.");
3584
3585   ("mke2journal_U", (RErr, [Int "blocksize"; String "uuid"; Device "device"]), 190, [],
3586    (let uuid = uuidgen () in
3587     [InitEmpty, Always, TestOutput (
3588        [["sfdiskM"; "/dev/sda"; ",100 ,"];
3589         ["mke2journal_U"; "4096"; uuid; "/dev/sda1"];
3590         ["mke2fs_JU"; "ext2"; "4096"; "/dev/sda2"; uuid];
3591         ["mount"; "/dev/sda2"; "/"];
3592         ["write_file"; "/new"; "new file contents"; "0"];
3593         ["cat"; "/new"]], "new file contents")]),
3594    "make ext2/3/4 external journal with UUID",
3595    "\
3596 This creates an ext2 external journal on C<device> with UUID C<uuid>.");
3597
3598   ("mke2fs_J", (RErr, [String "fstype"; Int "blocksize"; Device "device"; Device "journal"]), 191, [],
3599    [],
3600    "make ext2/3/4 filesystem with external journal",
3601    "\
3602 This creates an ext2/3/4 filesystem on C<device> with
3603 an external journal on C<journal>.  It is equivalent
3604 to the command:
3605
3606  mke2fs -t fstype -b blocksize -J device=<journal> <device>
3607
3608 See also C<guestfs_mke2journal>.");
3609
3610   ("mke2fs_JL", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "label"]), 192, [],
3611    [],
3612    "make ext2/3/4 filesystem with external journal",
3613    "\
3614 This creates an ext2/3/4 filesystem on C<device> with
3615 an external journal on the journal labeled C<label>.
3616
3617 See also C<guestfs_mke2journal_L>.");
3618
3619   ("mke2fs_JU", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "uuid"]), 193, [],
3620    [],
3621    "make ext2/3/4 filesystem with external journal",
3622    "\
3623 This creates an ext2/3/4 filesystem on C<device> with
3624 an external journal on the journal with UUID C<uuid>.
3625
3626 See also C<guestfs_mke2journal_U>.");
3627
3628   ("modprobe", (RErr, [String "modulename"]), 194, [],
3629    [InitNone, Always, TestRun [["modprobe"; "fat"]]],
3630    "load a kernel module",
3631    "\
3632 This loads a kernel module in the appliance.
3633
3634 The kernel module must have been whitelisted when libguestfs
3635 was built (see C<appliance/kmod.whitelist.in> in the source).");
3636
3637   ("echo_daemon", (RString "output", [StringList "words"]), 195, [],
3638    [InitNone, Always, TestOutput (
3639      [["echo_daemon"; "This is a test"]], "This is a test"
3640    )],
3641    "echo arguments back to the client",
3642    "\
3643 This command concatenate the list of C<words> passed with single spaces between
3644 them and returns the resulting string.
3645
3646 You can use this command to test the connection through to the daemon.
3647
3648 See also C<guestfs_ping_daemon>.");
3649
3650   ("find0", (RErr, [Pathname "directory"; FileOut "files"]), 196, [],
3651    [], (* There is a regression test for this. *)
3652    "find all files and directories, returning NUL-separated list",
3653    "\
3654 This command lists out all files and directories, recursively,
3655 starting at C<directory>, placing the resulting list in the
3656 external file called C<files>.
3657
3658 This command works the same way as C<guestfs_find> with the
3659 following exceptions:
3660
3661 =over 4
3662
3663 =item *
3664
3665 The resulting list is written to an external file.
3666
3667 =item *
3668
3669 Items (filenames) in the result are separated
3670 by C<\\0> characters.  See L<find(1)> option I<-print0>.
3671
3672 =item *
3673
3674 This command is not limited in the number of names that it
3675 can return.
3676
3677 =item *
3678
3679 The result list is not sorted.
3680
3681 =back");
3682
3683   ("case_sensitive_path", (RString "rpath", [Pathname "path"]), 197, [],
3684    [InitISOFS, Always, TestOutput (
3685       [["case_sensitive_path"; "/DIRECTORY"]], "/directory");
3686     InitISOFS, Always, TestOutput (
3687       [["case_sensitive_path"; "/DIRECTORY/"]], "/directory");
3688     InitISOFS, Always, TestOutput (
3689       [["case_sensitive_path"; "/Known-1"]], "/known-1");
3690     InitISOFS, Always, TestLastFail (
3691       [["case_sensitive_path"; "/Known-1/"]]);
3692     InitBasicFS, Always, TestOutput (
3693       [["mkdir"; "/a"];
3694        ["mkdir"; "/a/bbb"];
3695        ["touch"; "/a/bbb/c"];
3696        ["case_sensitive_path"; "/A/bbB/C"]], "/a/bbb/c");
3697     InitBasicFS, Always, TestOutput (
3698       [["mkdir"; "/a"];
3699        ["mkdir"; "/a/bbb"];
3700        ["touch"; "/a/bbb/c"];
3701        ["case_sensitive_path"; "/A////bbB/C"]], "/a/bbb/c");
3702     InitBasicFS, Always, TestLastFail (
3703       [["mkdir"; "/a"];
3704        ["mkdir"; "/a/bbb"];
3705        ["touch"; "/a/bbb/c"];
3706        ["case_sensitive_path"; "/A/bbb/../bbb/C"]])],
3707    "return true path on case-insensitive filesystem",
3708    "\
3709 This can be used to resolve case insensitive paths on
3710 a filesystem which is case sensitive.  The use case is
3711 to resolve paths which you have read from Windows configuration
3712 files or the Windows Registry, to the true path.
3713
3714 The command handles a peculiarity of the Linux ntfs-3g
3715 filesystem driver (and probably others), which is that although
3716 the underlying filesystem is case-insensitive, the driver
3717 exports the filesystem to Linux as case-sensitive.
3718
3719 One consequence of this is that special directories such
3720 as C<c:\\windows> may appear as C</WINDOWS> or C</windows>
3721 (or other things) depending on the precise details of how
3722 they were created.  In Windows itself this would not be
3723 a problem.
3724
3725 Bug or feature?  You decide:
3726 L<http://www.tuxera.com/community/ntfs-3g-faq/#posixfilenames1>
3727
3728 This function resolves the true case of each element in the
3729 path and returns the case-sensitive path.
3730
3731 Thus C<guestfs_case_sensitive_path> (\"/Windows/System32\")
3732 might return C<\"/WINDOWS/system32\"> (the exact return value
3733 would depend on details of how the directories were originally
3734 created under Windows).
3735
3736 I<Note>:
3737 This function does not handle drive names, backslashes etc.
3738
3739 See also C<guestfs_realpath>.");
3740
3741   ("vfs_type", (RString "fstype", [Device "device"]), 198, [],
3742    [InitBasicFS, Always, TestOutput (
3743       [["vfs_type"; "/dev/sda1"]], "ext2")],
3744    "get the Linux VFS type corresponding to a mounted device",
3745    "\
3746 This command gets the block device type corresponding to
3747 a mounted device called C<device>.
3748
3749 Usually the result is the name of the Linux VFS module that
3750 is used to mount this device (probably determined automatically
3751 if you used the C<guestfs_mount> call).");
3752
3753   ("truncate", (RErr, [Pathname "path"]), 199, [],
3754    [InitBasicFS, Always, TestOutputStruct (
3755       [["write_file"; "/test"; "some stuff so size is not zero"; "0"];
3756        ["truncate"; "/test"];
3757        ["stat"; "/test"]], [CompareWithInt ("size", 0)])],
3758    "truncate a file to zero size",
3759    "\
3760 This command truncates C<path> to a zero-length file.  The
3761 file must exist already.");
3762
3763   ("truncate_size", (RErr, [Pathname "path"; Int64 "size"]), 200, [],
3764    [InitBasicFS, Always, TestOutputStruct (
3765       [["touch"; "/test"];
3766        ["truncate_size"; "/test"; "1000"];
3767        ["stat"; "/test"]], [CompareWithInt ("size", 1000)])],
3768    "truncate a file to a particular size",
3769    "\
3770 This command truncates C<path> to size C<size> bytes.  The file
3771 must exist already.  If the file is smaller than C<size> then
3772 the file is extended to the required size with null bytes.");
3773
3774   ("utimens", (RErr, [Pathname "path"; Int64 "atsecs"; Int64 "atnsecs"; Int64 "mtsecs"; Int64 "mtnsecs"]), 201, [],
3775    [InitBasicFS, Always, TestOutputStruct (
3776       [["touch"; "/test"];
3777        ["utimens"; "/test"; "12345"; "67890"; "9876"; "5432"];
3778        ["stat"; "/test"]], [CompareWithInt ("mtime", 9876)])],
3779    "set timestamp of a file with nanosecond precision",
3780    "\
3781 This command sets the timestamps of a file with nanosecond
3782 precision.
3783
3784 C<atsecs, atnsecs> are the last access time (atime) in secs and
3785 nanoseconds from the epoch.
3786
3787 C<mtsecs, mtnsecs> are the last modification time (mtime) in
3788 secs and nanoseconds from the epoch.
3789
3790 If the C<*nsecs> field contains the special value C<-1> then
3791 the corresponding timestamp is set to the current time.  (The
3792 C<*secs> field is ignored in this case).
3793
3794 If the C<*nsecs> field contains the special value C<-2> then
3795 the corresponding timestamp is left unchanged.  (The
3796 C<*secs> field is ignored in this case).");
3797
3798   ("mkdir_mode", (RErr, [Pathname "path"; Int "mode"]), 202, [],
3799    [InitBasicFS, Always, TestOutputStruct (
3800       [["mkdir_mode"; "/test"; "0o111"];
3801        ["stat"; "/test"]], [CompareWithInt ("mode", 0o40111)])],
3802    "create a directory with a particular mode",
3803    "\
3804 This command creates a directory, setting the initial permissions
3805 of the directory to C<mode>.  See also C<guestfs_mkdir>.");
3806
3807   ("lchown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 203, [],
3808    [], (* XXX *)
3809    "change file owner and group",
3810    "\
3811 Change the file owner to C<owner> and group to C<group>.
3812 This is like C<guestfs_chown> but if C<path> is a symlink then
3813 the link itself is changed, not the target.
3814
3815 Only numeric uid and gid are supported.  If you want to use
3816 names, you will need to locate and parse the password file
3817 yourself (Augeas support makes this relatively easy).");
3818
3819   ("lstatlist", (RStructList ("statbufs", "stat"), [Pathname "path"; StringList "names"]), 204, [],
3820    [], (* XXX *)
3821    "lstat on multiple files",
3822    "\
3823 This call allows you to perform the C<guestfs_lstat> operation
3824 on multiple files, where all files are in the directory C<path>.
3825 C<names> is the list of files from this directory.
3826
3827 On return you get a list of stat structs, with a one-to-one
3828 correspondence to the C<names> list.  If any name did not exist
3829 or could not be lstat'd, then the C<ino> field of that structure
3830 is set to C<-1>.
3831
3832 This call is intended for programs that want to efficiently
3833 list a directory contents without making many round-trips.
3834 See also C<guestfs_lxattrlist> for a similarly efficient call
3835 for getting extended attributes.  Very long directory listings
3836 might cause the protocol message size to be exceeded, causing
3837 this call to fail.  The caller must split up such requests
3838 into smaller groups of names.");
3839
3840   ("lxattrlist", (RStructList ("xattrs", "xattr"), [Pathname "path"; StringList "names"]), 205, [],
3841    [], (* XXX *)
3842    "lgetxattr on multiple files",
3843    "\
3844 This call allows you to get the extended attributes
3845 of multiple files, where all files are in the directory C<path>.
3846 C<names> is the list of files from this directory.
3847
3848 On return you get a flat list of xattr structs which must be
3849 interpreted sequentially.  The first xattr struct always has a zero-length
3850 C<attrname>.  C<attrval> in this struct is zero-length
3851 to indicate there was an error doing C<lgetxattr> for this
3852 file, I<or> is a C string which is a decimal number
3853 (the number of following attributes for this file, which could
3854 be C<\"0\">).  Then after the first xattr struct are the
3855 zero or more attributes for the first named file.
3856 This repeats for the second and subsequent files.
3857
3858 This call is intended for programs that want to efficiently
3859 list a directory contents without making many round-trips.
3860 See also C<guestfs_lstatlist> for a similarly efficient call
3861 for getting standard stats.  Very long directory listings
3862 might cause the protocol message size to be exceeded, causing
3863 this call to fail.  The caller must split up such requests
3864 into smaller groups of names.");
3865
3866   ("readlinklist", (RStringList "links", [Pathname "path"; StringList "names"]), 206, [],
3867    [], (* XXX *)
3868    "readlink on multiple files",
3869    "\
3870 This call allows you to do a C<readlink> operation
3871 on multiple files, where all files are in the directory C<path>.
3872 C<names> is the list of files from this directory.
3873
3874 On return you get a list of strings, with a one-to-one
3875 correspondence to the C<names> list.  Each string is the
3876 value of the symbol link.
3877
3878 If the C<readlink(2)> operation fails on any name, then
3879 the corresponding result string is the empty string C<\"\">.
3880 However the whole operation is completed even if there
3881 were C<readlink(2)> errors, and so you can call this
3882 function with names where you don't know if they are
3883 symbolic links already (albeit slightly less efficient).
3884
3885 This call is intended for programs that want to efficiently
3886 list a directory contents without making many round-trips.
3887 Very long directory listings might cause the protocol
3888 message size to be exceeded, causing
3889 this call to fail.  The caller must split up such requests
3890 into smaller groups of names.");
3891
3892   ("pread", (RBufferOut "content", [Pathname "path"; Int "count"; Int64 "offset"]), 207, [ProtocolLimitWarning],
3893    [InitISOFS, Always, TestOutputBuffer (
3894       [["pread"; "/known-4"; "1"; "3"]], "\n");
3895     InitISOFS, Always, TestOutputBuffer (
3896       [["pread"; "/empty"; "0"; "100"]], "")],
3897    "read part of a file",
3898    "\
3899 This command lets you read part of a file.  It reads C<count>
3900 bytes of the file, starting at C<offset>, from file C<path>.
3901
3902 This may read fewer bytes than requested.  For further details
3903 see the L<pread(2)> system call.");
3904
3905   ("part_init", (RErr, [Device "device"; String "parttype"]), 208, [],
3906    [InitEmpty, Always, TestRun (
3907       [["part_init"; "/dev/sda"; "gpt"]])],
3908    "create an empty partition table",
3909    "\
3910 This creates an empty partition table on C<device> of one of the
3911 partition types listed below.  Usually C<parttype> should be
3912 either C<msdos> or C<gpt> (for large disks).
3913
3914 Initially there are no partitions.  Following this, you should
3915 call C<guestfs_part_add> for each partition required.
3916
3917 Possible values for C<parttype> are:
3918
3919 =over 4
3920
3921 =item B<efi> | B<gpt>
3922
3923 Intel EFI / GPT partition table.
3924
3925 This is recommended for >= 2 TB partitions that will be accessed
3926 from Linux and Intel-based Mac OS X.  It also has limited backwards
3927 compatibility with the C<mbr> format.
3928
3929 =item B<mbr> | B<msdos>
3930
3931 The standard PC \"Master Boot Record\" (MBR) format used
3932 by MS-DOS and Windows.  This partition type will B<only> work
3933 for device sizes up to 2 TB.  For large disks we recommend
3934 using C<gpt>.
3935
3936 =back
3937
3938 Other partition table types that may work but are not
3939 supported include:
3940
3941 =over 4
3942
3943 =item B<aix>
3944
3945 AIX disk labels.
3946
3947 =item B<amiga> | B<rdb>
3948
3949 Amiga \"Rigid Disk Block\" format.
3950
3951 =item B<bsd>
3952
3953 BSD disk labels.
3954
3955 =item B<dasd>
3956
3957 DASD, used on IBM mainframes.
3958
3959 =item B<dvh>
3960
3961 MIPS/SGI volumes.
3962
3963 =item B<mac>
3964
3965 Old Mac partition format.  Modern Macs use C<gpt>.
3966
3967 =item B<pc98>
3968
3969 NEC PC-98 format, common in Japan apparently.
3970
3971 =item B<sun>
3972
3973 Sun disk labels.
3974
3975 =back");
3976
3977   ("part_add", (RErr, [Device "device"; String "prlogex"; Int64 "startsect"; Int64 "endsect"]), 209, [],
3978    [InitEmpty, Always, TestRun (
3979       [["part_init"; "/dev/sda"; "mbr"];
3980        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"]]);
3981     InitEmpty, Always, TestRun (
3982       [["part_init"; "/dev/sda"; "gpt"];
3983        ["part_add"; "/dev/sda"; "primary"; "34"; "127"];
3984        ["part_add"; "/dev/sda"; "primary"; "128"; "-34"]]);
3985     InitEmpty, Always, TestRun (
3986       [["part_init"; "/dev/sda"; "mbr"];
3987        ["part_add"; "/dev/sda"; "primary"; "32"; "127"];
3988        ["part_add"; "/dev/sda"; "primary"; "128"; "255"];
3989        ["part_add"; "/dev/sda"; "primary"; "256"; "511"];
3990        ["part_add"; "/dev/sda"; "primary"; "512"; "-1"]])],
3991    "add a partition to the device",
3992    "\
3993 This command adds a partition to C<device>.  If there is no partition
3994 table on the device, call C<guestfs_part_init> first.
3995
3996 The C<prlogex> parameter is the type of partition.  Normally you
3997 should pass C<p> or C<primary> here, but MBR partition tables also
3998 support C<l> (or C<logical>) and C<e> (or C<extended>) partition
3999 types.
4000
4001 C<startsect> and C<endsect> are the start and end of the partition
4002 in I<sectors>.  C<endsect> may be negative, which means it counts
4003 backwards from the end of the disk (C<-1> is the last sector).
4004
4005 Creating a partition which covers the whole disk is not so easy.
4006 Use C<guestfs_part_disk> to do that.");
4007
4008   ("part_disk", (RErr, [Device "device"; String "parttype"]), 210, [DangerWillRobinson],
4009    [InitEmpty, Always, TestRun (
4010       [["part_disk"; "/dev/sda"; "mbr"]]);
4011     InitEmpty, Always, TestRun (
4012       [["part_disk"; "/dev/sda"; "gpt"]])],
4013    "partition whole disk with a single primary partition",
4014    "\
4015 This command is simply a combination of C<guestfs_part_init>
4016 followed by C<guestfs_part_add> to create a single primary partition
4017 covering the whole disk.
4018
4019 C<parttype> is the partition table type, usually C<mbr> or C<gpt>,
4020 but other possible values are described in C<guestfs_part_init>.");
4021
4022   ("part_set_bootable", (RErr, [Device "device"; Int "partnum"; Bool "bootable"]), 211, [],
4023    [InitEmpty, Always, TestRun (
4024       [["part_disk"; "/dev/sda"; "mbr"];
4025        ["part_set_bootable"; "/dev/sda"; "1"; "true"]])],
4026    "make a partition bootable",
4027    "\
4028 This sets the bootable flag on partition numbered C<partnum> on
4029 device C<device>.  Note that partitions are numbered from 1.
4030
4031 The bootable flag is used by some PC BIOSes to determine which
4032 partition to boot from.  It is by no means universally recognized,
4033 and in any case if your operating system installed a boot
4034 sector on the device itself, then that takes precedence.");
4035
4036   ("part_set_name", (RErr, [Device "device"; Int "partnum"; String "name"]), 212, [],
4037    [InitEmpty, Always, TestRun (
4038       [["part_disk"; "/dev/sda"; "gpt"];
4039        ["part_set_name"; "/dev/sda"; "1"; "thepartname"]])],
4040    "set partition name",
4041    "\
4042 This sets the partition name on partition numbered C<partnum> on
4043 device C<device>.  Note that partitions are numbered from 1.
4044
4045 The partition name can only be set on certain types of partition
4046 table.  This works on C<gpt> but not on C<mbr> partitions.");
4047
4048   ("part_list", (RStructList ("partitions", "partition"), [Device "device"]), 213, [],
4049    [], (* XXX Add a regression test for this. *)
4050    "list partitions on a device",
4051    "\
4052 This command parses the partition table on C<device> and
4053 returns the list of partitions found.
4054
4055 The fields in the returned structure are:
4056
4057 =over 4
4058
4059 =item B<part_num>
4060
4061 Partition number, counting from 1.
4062
4063 =item B<part_start>
4064
4065 Start of the partition I<in bytes>.  To get sectors you have to
4066 divide by the device's sector size, see C<guestfs_blockdev_getss>.
4067
4068 =item B<part_end>
4069
4070 End of the partition in bytes.
4071
4072 =item B<part_size>
4073
4074 Size of the partition in bytes.
4075
4076 =back");
4077
4078   ("part_get_parttype", (RString "parttype", [Device "device"]), 214, [],
4079    [InitEmpty, Always, TestOutput (
4080       [["part_disk"; "/dev/sda"; "gpt"];
4081        ["part_get_parttype"; "/dev/sda"]], "gpt")],
4082    "get the partition table type",
4083    "\
4084 This command examines the partition table on C<device> and
4085 returns the partition table type (format) being used.
4086
4087 Common return values include: C<msdos> (a DOS/Windows style MBR
4088 partition table), C<gpt> (a GPT/EFI-style partition table).  Other
4089 values are possible, although unusual.  See C<guestfs_part_init>
4090 for a full list.");
4091
4092   ("fill", (RErr, [Int "c"; Int "len"; Pathname "path"]), 215, [],
4093    [InitBasicFS, Always, TestOutputBuffer (
4094       [["fill"; "0x63"; "10"; "/test"];
4095        ["read_file"; "/test"]], "cccccccccc")],
4096    "fill a file with octets",
4097    "\
4098 This command creates a new file called C<path>.  The initial
4099 content of the file is C<len> octets of C<c>, where C<c>
4100 must be a number in the range C<[0..255]>.
4101
4102 To fill a file with zero bytes (sparsely), it is
4103 much more efficient to use C<guestfs_truncate_size>.");
4104
4105 ]
4106
4107 let all_functions = non_daemon_functions @ daemon_functions
4108
4109 (* In some places we want the functions to be displayed sorted
4110  * alphabetically, so this is useful:
4111  *)
4112 let all_functions_sorted =
4113   List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
4114                compare n1 n2) all_functions
4115
4116 (* Field types for structures. *)
4117 type field =
4118   | FChar                       (* C 'char' (really, a 7 bit byte). *)
4119   | FString                     (* nul-terminated ASCII string, NOT NULL. *)
4120   | FBuffer                     (* opaque buffer of bytes, (char *, int) pair *)
4121   | FUInt32
4122   | FInt32
4123   | FUInt64
4124   | FInt64
4125   | FBytes                      (* Any int measure that counts bytes. *)
4126   | FUUID                       (* 32 bytes long, NOT nul-terminated. *)
4127   | FOptPercent                 (* [0..100], or -1 meaning "not present". *)
4128
4129 (* Because we generate extra parsing code for LVM command line tools,
4130  * we have to pull out the LVM columns separately here.
4131  *)
4132 let lvm_pv_cols = [
4133   "pv_name", FString;
4134   "pv_uuid", FUUID;
4135   "pv_fmt", FString;
4136   "pv_size", FBytes;
4137   "dev_size", FBytes;
4138   "pv_free", FBytes;
4139   "pv_used", FBytes;
4140   "pv_attr", FString (* XXX *);
4141   "pv_pe_count", FInt64;
4142   "pv_pe_alloc_count", FInt64;
4143   "pv_tags", FString;
4144   "pe_start", FBytes;
4145   "pv_mda_count", FInt64;
4146   "pv_mda_free", FBytes;
4147   (* Not in Fedora 10:
4148      "pv_mda_size", FBytes;
4149   *)
4150 ]
4151 let lvm_vg_cols = [
4152   "vg_name", FString;
4153   "vg_uuid", FUUID;
4154   "vg_fmt", FString;
4155   "vg_attr", FString (* XXX *);
4156   "vg_size", FBytes;
4157   "vg_free", FBytes;
4158   "vg_sysid", FString;
4159   "vg_extent_size", FBytes;
4160   "vg_extent_count", FInt64;
4161   "vg_free_count", FInt64;
4162   "max_lv", FInt64;
4163   "max_pv", FInt64;
4164   "pv_count", FInt64;
4165   "lv_count", FInt64;
4166   "snap_count", FInt64;
4167   "vg_seqno", FInt64;
4168   "vg_tags", FString;
4169   "vg_mda_count", FInt64;
4170   "vg_mda_free", FBytes;
4171   (* Not in Fedora 10:
4172      "vg_mda_size", FBytes;
4173   *)
4174 ]
4175 let lvm_lv_cols = [
4176   "lv_name", FString;
4177   "lv_uuid", FUUID;
4178   "lv_attr", FString (* XXX *);
4179   "lv_major", FInt64;
4180   "lv_minor", FInt64;
4181   "lv_kernel_major", FInt64;
4182   "lv_kernel_minor", FInt64;
4183   "lv_size", FBytes;
4184   "seg_count", FInt64;
4185   "origin", FString;
4186   "snap_percent", FOptPercent;
4187   "copy_percent", FOptPercent;
4188   "move_pv", FString;
4189   "lv_tags", FString;
4190   "mirror_log", FString;
4191   "modules", FString;
4192 ]
4193
4194 (* Names and fields in all structures (in RStruct and RStructList)
4195  * that we support.
4196  *)
4197 let structs = [
4198   (* The old RIntBool return type, only ever used for aug_defnode.  Do
4199    * not use this struct in any new code.
4200    *)
4201   "int_bool", [
4202     "i", FInt32;                (* for historical compatibility *)
4203     "b", FInt32;                (* for historical compatibility *)
4204   ];
4205
4206   (* LVM PVs, VGs, LVs. *)
4207   "lvm_pv", lvm_pv_cols;
4208   "lvm_vg", lvm_vg_cols;
4209   "lvm_lv", lvm_lv_cols;
4210
4211   (* Column names and types from stat structures.
4212    * NB. Can't use things like 'st_atime' because glibc header files
4213    * define some of these as macros.  Ugh.
4214    *)
4215   "stat", [
4216     "dev", FInt64;
4217     "ino", FInt64;
4218     "mode", FInt64;
4219     "nlink", FInt64;
4220     "uid", FInt64;
4221     "gid", FInt64;
4222     "rdev", FInt64;
4223     "size", FInt64;
4224     "blksize", FInt64;
4225     "blocks", FInt64;
4226     "atime", FInt64;
4227     "mtime", FInt64;
4228     "ctime", FInt64;
4229   ];
4230   "statvfs", [
4231     "bsize", FInt64;
4232     "frsize", FInt64;
4233     "blocks", FInt64;
4234     "bfree", FInt64;
4235     "bavail", FInt64;
4236     "files", FInt64;
4237     "ffree", FInt64;
4238     "favail", FInt64;
4239     "fsid", FInt64;
4240     "flag", FInt64;
4241     "namemax", FInt64;
4242   ];
4243
4244   (* Column names in dirent structure. *)
4245   "dirent", [
4246     "ino", FInt64;
4247     (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
4248     "ftyp", FChar;
4249     "name", FString;
4250   ];
4251
4252   (* Version numbers. *)
4253   "version", [
4254     "major", FInt64;
4255     "minor", FInt64;
4256     "release", FInt64;
4257     "extra", FString;
4258   ];
4259
4260   (* Extended attribute. *)
4261   "xattr", [
4262     "attrname", FString;
4263     "attrval", FBuffer;
4264   ];
4265
4266   (* Inotify events. *)
4267   "inotify_event", [
4268     "in_wd", FInt64;
4269     "in_mask", FUInt32;
4270     "in_cookie", FUInt32;
4271     "in_name", FString;
4272   ];
4273
4274   (* Partition table entry. *)
4275   "partition", [
4276     "part_num", FInt32;
4277     "part_start", FBytes;
4278     "part_end", FBytes;
4279     "part_size", FBytes;
4280   ];
4281 ] (* end of structs *)
4282
4283 (* Ugh, Java has to be different ..
4284  * These names are also used by the Haskell bindings.
4285  *)
4286 let java_structs = [
4287   "int_bool", "IntBool";
4288   "lvm_pv", "PV";
4289   "lvm_vg", "VG";
4290   "lvm_lv", "LV";
4291   "stat", "Stat";
4292   "statvfs", "StatVFS";
4293   "dirent", "Dirent";
4294   "version", "Version";
4295   "xattr", "XAttr";
4296   "inotify_event", "INotifyEvent";
4297   "partition", "Partition";
4298 ]
4299
4300 (* What structs are actually returned. *)
4301 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
4302
4303 (* Returns a list of RStruct/RStructList structs that are returned
4304  * by any function.  Each element of returned list is a pair:
4305  *
4306  * (structname, RStructOnly)
4307  *    == there exists function which returns RStruct (_, structname)
4308  * (structname, RStructListOnly)
4309  *    == there exists function which returns RStructList (_, structname)
4310  * (structname, RStructAndList)
4311  *    == there are functions returning both RStruct (_, structname)
4312  *                                      and RStructList (_, structname)
4313  *)
4314 let rstructs_used_by functions =
4315   (* ||| is a "logical OR" for rstructs_used_t *)
4316   let (|||) a b =
4317     match a, b with
4318     | RStructAndList, _
4319     | _, RStructAndList -> RStructAndList
4320     | RStructOnly, RStructListOnly
4321     | RStructListOnly, RStructOnly -> RStructAndList
4322     | RStructOnly, RStructOnly -> RStructOnly
4323     | RStructListOnly, RStructListOnly -> RStructListOnly
4324   in
4325
4326   let h = Hashtbl.create 13 in
4327
4328   (* if elem->oldv exists, update entry using ||| operator,
4329    * else just add elem->newv to the hash
4330    *)
4331   let update elem newv =
4332     try  let oldv = Hashtbl.find h elem in
4333          Hashtbl.replace h elem (newv ||| oldv)
4334     with Not_found -> Hashtbl.add h elem newv
4335   in
4336
4337   List.iter (
4338     fun (_, style, _, _, _, _, _) ->
4339       match fst style with
4340       | RStruct (_, structname) -> update structname RStructOnly
4341       | RStructList (_, structname) -> update structname RStructListOnly
4342       | _ -> ()
4343   ) functions;
4344
4345   (* return key->values as a list of (key,value) *)
4346   Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
4347
4348 (* Used for testing language bindings. *)
4349 type callt =
4350   | CallString of string
4351   | CallOptString of string option
4352   | CallStringList of string list
4353   | CallInt of int
4354   | CallInt64 of int64
4355   | CallBool of bool
4356
4357 (* Used to memoize the result of pod2text. *)
4358 let pod2text_memo_filename = "src/.pod2text.data"
4359 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
4360   try
4361     let chan = open_in pod2text_memo_filename in
4362     let v = input_value chan in
4363     close_in chan;
4364     v
4365   with
4366     _ -> Hashtbl.create 13
4367 let pod2text_memo_updated () =
4368   let chan = open_out pod2text_memo_filename in
4369   output_value chan pod2text_memo;
4370   close_out chan
4371
4372 (* Useful functions.
4373  * Note we don't want to use any external OCaml libraries which
4374  * makes this a bit harder than it should be.
4375  *)
4376 let failwithf fs = ksprintf failwith fs
4377
4378 let replace_char s c1 c2 =
4379   let s2 = String.copy s in
4380   let r = ref false in
4381   for i = 0 to String.length s2 - 1 do
4382     if String.unsafe_get s2 i = c1 then (
4383       String.unsafe_set s2 i c2;
4384       r := true
4385     )
4386   done;
4387   if not !r then s else s2
4388
4389 let isspace c =
4390   c = ' '
4391   (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
4392
4393 let triml ?(test = isspace) str =
4394   let i = ref 0 in
4395   let n = ref (String.length str) in
4396   while !n > 0 && test str.[!i]; do
4397     decr n;
4398     incr i
4399   done;
4400   if !i = 0 then str
4401   else String.sub str !i !n
4402
4403 let trimr ?(test = isspace) str =
4404   let n = ref (String.length str) in
4405   while !n > 0 && test str.[!n-1]; do
4406     decr n
4407   done;
4408   if !n = String.length str then str
4409   else String.sub str 0 !n
4410
4411 let trim ?(test = isspace) str =
4412   trimr ~test (triml ~test str)
4413
4414 let rec find s sub =
4415   let len = String.length s in
4416   let sublen = String.length sub in
4417   let rec loop i =
4418     if i <= len-sublen then (
4419       let rec loop2 j =
4420         if j < sublen then (
4421           if s.[i+j] = sub.[j] then loop2 (j+1)
4422           else -1
4423         ) else
4424           i (* found *)
4425       in
4426       let r = loop2 0 in
4427       if r = -1 then loop (i+1) else r
4428     ) else
4429       -1 (* not found *)
4430   in
4431   loop 0
4432
4433 let rec replace_str s s1 s2 =
4434   let len = String.length s in
4435   let sublen = String.length s1 in
4436   let i = find s s1 in
4437   if i = -1 then s
4438   else (
4439     let s' = String.sub s 0 i in
4440     let s'' = String.sub s (i+sublen) (len-i-sublen) in
4441     s' ^ s2 ^ replace_str s'' s1 s2
4442   )
4443
4444 let rec string_split sep str =
4445   let len = String.length str in
4446   let seplen = String.length sep in
4447   let i = find str sep in
4448   if i = -1 then [str]
4449   else (
4450     let s' = String.sub str 0 i in
4451     let s'' = String.sub str (i+seplen) (len-i-seplen) in
4452     s' :: string_split sep s''
4453   )
4454
4455 let files_equal n1 n2 =
4456   let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
4457   match Sys.command cmd with
4458   | 0 -> true
4459   | 1 -> false
4460   | i -> failwithf "%s: failed with error code %d" cmd i
4461
4462 let rec filter_map f = function
4463   | [] -> []
4464   | x :: xs ->
4465       match f x with
4466       | Some y -> y :: filter_map f xs
4467       | None -> filter_map f xs
4468
4469 let rec find_map f = function
4470   | [] -> raise Not_found
4471   | x :: xs ->
4472       match f x with
4473       | Some y -> y
4474       | None -> find_map f xs
4475
4476 let iteri f xs =
4477   let rec loop i = function
4478     | [] -> ()
4479     | x :: xs -> f i x; loop (i+1) xs
4480   in
4481   loop 0 xs
4482
4483 let mapi f xs =
4484   let rec loop i = function
4485     | [] -> []
4486     | x :: xs -> let r = f i x in r :: loop (i+1) xs
4487   in
4488   loop 0 xs
4489
4490 let name_of_argt = function
4491   | Pathname n | Device n | Dev_or_Path n | String n | OptString n
4492   | StringList n | DeviceList n | Bool n | Int n | Int64 n
4493   | FileIn n | FileOut n -> n
4494
4495 let java_name_of_struct typ =
4496   try List.assoc typ java_structs
4497   with Not_found ->
4498     failwithf
4499       "java_name_of_struct: no java_structs entry corresponding to %s" typ
4500
4501 let cols_of_struct typ =
4502   try List.assoc typ structs
4503   with Not_found ->
4504     failwithf "cols_of_struct: unknown struct %s" typ
4505
4506 let seq_of_test = function
4507   | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
4508   | TestOutputListOfDevices (s, _)
4509   | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
4510   | TestOutputTrue s | TestOutputFalse s
4511   | TestOutputLength (s, _) | TestOutputBuffer (s, _)
4512   | TestOutputStruct (s, _)
4513   | TestLastFail s -> s
4514
4515 (* Handling for function flags. *)
4516 let protocol_limit_warning =
4517   "Because of the message protocol, there is a transfer limit
4518 of somewhere between 2MB and 4MB.  To transfer large files you should use
4519 FTP."
4520
4521 let danger_will_robinson =
4522   "B<This command is dangerous.  Without careful use you
4523 can easily destroy all your data>."
4524
4525 let deprecation_notice flags =
4526   try
4527     let alt =
4528       find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
4529     let txt =
4530       sprintf "This function is deprecated.
4531 In new code, use the C<%s> call instead.
4532
4533 Deprecated functions will not be removed from the API, but the
4534 fact that they are deprecated indicates that there are problems
4535 with correct use of these functions." alt in
4536     Some txt
4537   with
4538     Not_found -> None
4539
4540 (* Check function names etc. for consistency. *)
4541 let check_functions () =
4542   let contains_uppercase str =
4543     let len = String.length str in
4544     let rec loop i =
4545       if i >= len then false
4546       else (
4547         let c = str.[i] in
4548         if c >= 'A' && c <= 'Z' then true
4549         else loop (i+1)
4550       )
4551     in
4552     loop 0
4553   in
4554
4555   (* Check function names. *)
4556   List.iter (
4557     fun (name, _, _, _, _, _, _) ->
4558       if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
4559         failwithf "function name %s does not need 'guestfs' prefix" name;
4560       if name = "" then
4561         failwithf "function name is empty";
4562       if name.[0] < 'a' || name.[0] > 'z' then
4563         failwithf "function name %s must start with lowercase a-z" name;
4564       if String.contains name '-' then
4565         failwithf "function name %s should not contain '-', use '_' instead."
4566           name
4567   ) all_functions;
4568
4569   (* Check function parameter/return names. *)
4570   List.iter (
4571     fun (name, style, _, _, _, _, _) ->
4572       let check_arg_ret_name n =
4573         if contains_uppercase n then
4574           failwithf "%s param/ret %s should not contain uppercase chars"
4575             name n;
4576         if String.contains n '-' || String.contains n '_' then
4577           failwithf "%s param/ret %s should not contain '-' or '_'"
4578             name n;
4579         if n = "value" then
4580           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;
4581         if n = "int" || n = "char" || n = "short" || n = "long" then
4582           failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
4583         if n = "i" || n = "n" then
4584           failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
4585         if n = "argv" || n = "args" then
4586           failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
4587
4588         (* List Haskell, OCaml and C keywords here.
4589          * http://www.haskell.org/haskellwiki/Keywords
4590          * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
4591          * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
4592          * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
4593          *   |perl -pe 's/(.+)/"$1";/'|fmt -70
4594          * Omitting _-containing words, since they're handled above.
4595          * Omitting the OCaml reserved word, "val", is ok,
4596          * and saves us from renaming several parameters.
4597          *)
4598         let reserved = [
4599           "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
4600           "char"; "class"; "const"; "constraint"; "continue"; "data";
4601           "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
4602           "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
4603           "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
4604           "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
4605           "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
4606           "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
4607           "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
4608           "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
4609           "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
4610           "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
4611           "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
4612           "volatile"; "when"; "where"; "while";
4613           ] in
4614         if List.mem n reserved then
4615           failwithf "%s has param/ret using reserved word %s" name n;
4616       in
4617
4618       (match fst style with
4619        | RErr -> ()
4620        | RInt n | RInt64 n | RBool n
4621        | RConstString n | RConstOptString n | RString n
4622        | RStringList n | RStruct (n, _) | RStructList (n, _)
4623        | RHashtable n | RBufferOut n ->
4624            check_arg_ret_name n
4625       );
4626       List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
4627   ) all_functions;
4628
4629   (* Check short descriptions. *)
4630   List.iter (
4631     fun (name, _, _, _, _, shortdesc, _) ->
4632       if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
4633         failwithf "short description of %s should begin with lowercase." name;
4634       let c = shortdesc.[String.length shortdesc-1] in
4635       if c = '\n' || c = '.' then
4636         failwithf "short description of %s should not end with . or \\n." name
4637   ) all_functions;
4638
4639   (* Check long dscriptions. *)
4640   List.iter (
4641     fun (name, _, _, _, _, _, longdesc) ->
4642       if longdesc.[String.length longdesc-1] = '\n' then
4643         failwithf "long description of %s should not end with \\n." name
4644   ) all_functions;
4645
4646   (* Check proc_nrs. *)
4647   List.iter (
4648     fun (name, _, proc_nr, _, _, _, _) ->
4649       if proc_nr <= 0 then
4650         failwithf "daemon function %s should have proc_nr > 0" name
4651   ) daemon_functions;
4652
4653   List.iter (
4654     fun (name, _, proc_nr, _, _, _, _) ->
4655       if proc_nr <> -1 then
4656         failwithf "non-daemon function %s should have proc_nr -1" name
4657   ) non_daemon_functions;
4658
4659   let proc_nrs =
4660     List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
4661       daemon_functions in
4662   let proc_nrs =
4663     List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
4664   let rec loop = function
4665     | [] -> ()
4666     | [_] -> ()
4667     | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
4668         loop rest
4669     | (name1,nr1) :: (name2,nr2) :: _ ->
4670         failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
4671           name1 name2 nr1 nr2
4672   in
4673   loop proc_nrs;
4674
4675   (* Check tests. *)
4676   List.iter (
4677     function
4678       (* Ignore functions that have no tests.  We generate a
4679        * warning when the user does 'make check' instead.
4680        *)
4681     | name, _, _, _, [], _, _ -> ()
4682     | name, _, _, _, tests, _, _ ->
4683         let funcs =
4684           List.map (
4685             fun (_, _, test) ->
4686               match seq_of_test test with
4687               | [] ->
4688                   failwithf "%s has a test containing an empty sequence" name
4689               | cmds -> List.map List.hd cmds
4690           ) tests in
4691         let funcs = List.flatten funcs in
4692
4693         let tested = List.mem name funcs in
4694
4695         if not tested then
4696           failwithf "function %s has tests but does not test itself" name
4697   ) all_functions
4698
4699 (* 'pr' prints to the current output file. *)
4700 let chan = ref Pervasives.stdout
4701 let pr fs = ksprintf (output_string !chan) fs
4702
4703 (* Generate a header block in a number of standard styles. *)
4704 type comment_style = CStyle | HashStyle | OCamlStyle | HaskellStyle
4705 type license = GPLv2 | LGPLv2
4706
4707 let generate_header comment license =
4708   let c = match comment with
4709     | CStyle ->     pr "/* "; " *"
4710     | HashStyle ->  pr "# ";  "#"
4711     | OCamlStyle -> pr "(* "; " *"
4712     | HaskellStyle -> pr "{- "; "  " in
4713   pr "libguestfs generated file\n";
4714   pr "%s WARNING: THIS FILE IS GENERATED BY 'src/generator.ml'.\n" c;
4715   pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
4716   pr "%s\n" c;
4717   pr "%s Copyright (C) 2009 Red Hat Inc.\n" c;
4718   pr "%s\n" c;
4719   (match license with
4720    | GPLv2 ->
4721        pr "%s This program is free software; you can redistribute it and/or modify\n" c;
4722        pr "%s it under the terms of the GNU General Public License as published by\n" c;
4723        pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
4724        pr "%s (at your option) any later version.\n" c;
4725        pr "%s\n" c;
4726        pr "%s This program is distributed in the hope that it will be useful,\n" c;
4727        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
4728        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n" c;
4729        pr "%s GNU General Public License for more details.\n" c;
4730        pr "%s\n" c;
4731        pr "%s You should have received a copy of the GNU General Public License along\n" c;
4732        pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
4733        pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
4734
4735    | LGPLv2 ->
4736        pr "%s This library is free software; you can redistribute it and/or\n" c;
4737        pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
4738        pr "%s License as published by the Free Software Foundation; either\n" c;
4739        pr "%s version 2 of the License, or (at your option) any later version.\n" c;
4740        pr "%s\n" c;
4741        pr "%s This library is distributed in the hope that it will be useful,\n" c;
4742        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
4743        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n" c;
4744        pr "%s Lesser General Public License for more details.\n" c;
4745        pr "%s\n" c;
4746        pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
4747        pr "%s License along with this library; if not, write to the Free Software\n" c;
4748        pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
4749   );
4750   (match comment with
4751    | CStyle -> pr " */\n"
4752    | HashStyle -> ()
4753    | OCamlStyle -> pr " *)\n"
4754    | HaskellStyle -> pr "-}\n"
4755   );
4756   pr "\n"
4757
4758 (* Start of main code generation functions below this line. *)
4759
4760 (* Generate the pod documentation for the C API. *)
4761 let rec generate_actions_pod () =
4762   List.iter (
4763     fun (shortname, style, _, flags, _, _, longdesc) ->
4764       if not (List.mem NotInDocs flags) then (
4765         let name = "guestfs_" ^ shortname in
4766         pr "=head2 %s\n\n" name;
4767         pr " ";
4768         generate_prototype ~extern:false ~handle:"handle" name style;
4769         pr "\n\n";
4770         pr "%s\n\n" longdesc;
4771         (match fst style with
4772          | RErr ->
4773              pr "This function returns 0 on success or -1 on error.\n\n"
4774          | RInt _ ->
4775              pr "On error this function returns -1.\n\n"
4776          | RInt64 _ ->
4777              pr "On error this function returns -1.\n\n"
4778          | RBool _ ->
4779              pr "This function returns a C truth value on success or -1 on error.\n\n"
4780          | RConstString _ ->
4781              pr "This function returns a string, or NULL on error.
4782 The string is owned by the guest handle and must I<not> be freed.\n\n"
4783          | RConstOptString _ ->
4784              pr "This function returns a string which may be NULL.
4785 There is way to return an error from this function.
4786 The string is owned by the guest handle and must I<not> be freed.\n\n"
4787          | RString _ ->
4788              pr "This function returns a string, or NULL on error.
4789 I<The caller must free the returned string after use>.\n\n"
4790          | RStringList _ ->
4791              pr "This function returns a NULL-terminated array of strings
4792 (like L<environ(3)>), or NULL if there was an error.
4793 I<The caller must free the strings and the array after use>.\n\n"
4794          | RStruct (_, typ) ->
4795              pr "This function returns a C<struct guestfs_%s *>,
4796 or NULL if there was an error.
4797 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
4798          | RStructList (_, typ) ->
4799              pr "This function returns a C<struct guestfs_%s_list *>
4800 (see E<lt>guestfs-structs.hE<gt>),
4801 or NULL if there was an error.
4802 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
4803          | RHashtable _ ->
4804              pr "This function returns a NULL-terminated array of
4805 strings, or NULL if there was an error.
4806 The array of strings will always have length C<2n+1>, where
4807 C<n> keys and values alternate, followed by the trailing NULL entry.
4808 I<The caller must free the strings and the array after use>.\n\n"
4809          | RBufferOut _ ->
4810              pr "This function returns a buffer, or NULL on error.
4811 The size of the returned buffer is written to C<*size_r>.
4812 I<The caller must free the returned buffer after use>.\n\n"
4813         );
4814         if List.mem ProtocolLimitWarning flags then
4815           pr "%s\n\n" protocol_limit_warning;
4816         if List.mem DangerWillRobinson flags then
4817           pr "%s\n\n" danger_will_robinson;
4818         match deprecation_notice flags with
4819         | None -> ()
4820         | Some txt -> pr "%s\n\n" txt
4821       )
4822   ) all_functions_sorted
4823
4824 and generate_structs_pod () =
4825   (* Structs documentation. *)
4826   List.iter (
4827     fun (typ, cols) ->
4828       pr "=head2 guestfs_%s\n" typ;
4829       pr "\n";
4830       pr " struct guestfs_%s {\n" typ;
4831       List.iter (
4832         function
4833         | name, FChar -> pr "   char %s;\n" name
4834         | name, FUInt32 -> pr "   uint32_t %s;\n" name
4835         | name, FInt32 -> pr "   int32_t %s;\n" name
4836         | name, (FUInt64|FBytes) -> pr "   uint64_t %s;\n" name
4837         | name, FInt64 -> pr "   int64_t %s;\n" name
4838         | name, FString -> pr "   char *%s;\n" name
4839         | name, FBuffer ->
4840             pr "   /* The next two fields describe a byte array. */\n";
4841             pr "   uint32_t %s_len;\n" name;
4842             pr "   char *%s;\n" name
4843         | name, FUUID ->
4844             pr "   /* The next field is NOT nul-terminated, be careful when printing it: */\n";
4845             pr "   char %s[32];\n" name
4846         | name, FOptPercent ->
4847             pr "   /* The next field is [0..100] or -1 meaning 'not present': */\n";
4848             pr "   float %s;\n" name
4849       ) cols;
4850       pr " };\n";
4851       pr " \n";
4852       pr " struct guestfs_%s_list {\n" typ;
4853       pr "   uint32_t len; /* Number of elements in list. */\n";
4854       pr "   struct guestfs_%s *val; /* Elements. */\n" typ;
4855       pr " };\n";
4856       pr " \n";
4857       pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
4858       pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
4859         typ typ;
4860       pr "\n"
4861   ) structs
4862
4863 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
4864  * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
4865  *
4866  * We have to use an underscore instead of a dash because otherwise
4867  * rpcgen generates incorrect code.
4868  *
4869  * This header is NOT exported to clients, but see also generate_structs_h.
4870  *)
4871 and generate_xdr () =
4872   generate_header CStyle LGPLv2;
4873
4874   (* This has to be defined to get around a limitation in Sun's rpcgen. *)
4875   pr "typedef string str<>;\n";
4876   pr "\n";
4877
4878   (* Internal structures. *)
4879   List.iter (
4880     function
4881     | typ, cols ->
4882         pr "struct guestfs_int_%s {\n" typ;
4883         List.iter (function
4884                    | name, FChar -> pr "  char %s;\n" name
4885                    | name, FString -> pr "  string %s<>;\n" name
4886                    | name, FBuffer -> pr "  opaque %s<>;\n" name
4887                    | name, FUUID -> pr "  opaque %s[32];\n" name
4888                    | name, (FInt32|FUInt32) -> pr "  int %s;\n" name
4889                    | name, (FInt64|FUInt64|FBytes) -> pr "  hyper %s;\n" name
4890                    | name, FOptPercent -> pr "  float %s;\n" name
4891                   ) cols;
4892         pr "};\n";
4893         pr "\n";
4894         pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
4895         pr "\n";
4896   ) structs;
4897
4898   List.iter (
4899     fun (shortname, style, _, _, _, _, _) ->
4900       let name = "guestfs_" ^ shortname in
4901
4902       (match snd style with
4903        | [] -> ()
4904        | args ->
4905            pr "struct %s_args {\n" name;
4906            List.iter (
4907              function
4908              | Pathname n | Device n | Dev_or_Path n | String n ->
4909                  pr "  string %s<>;\n" n
4910              | OptString n -> pr "  str *%s;\n" n
4911              | StringList n | DeviceList n -> pr "  str %s<>;\n" n
4912              | Bool n -> pr "  bool %s;\n" n
4913              | Int n -> pr "  int %s;\n" n
4914              | Int64 n -> pr "  hyper %s;\n" n
4915              | FileIn _ | FileOut _ -> ()
4916            ) args;
4917            pr "};\n\n"
4918       );
4919       (match fst style with
4920        | RErr -> ()
4921        | RInt n ->
4922            pr "struct %s_ret {\n" name;
4923            pr "  int %s;\n" n;
4924            pr "};\n\n"
4925        | RInt64 n ->
4926            pr "struct %s_ret {\n" name;
4927            pr "  hyper %s;\n" n;
4928            pr "};\n\n"
4929        | RBool n ->
4930            pr "struct %s_ret {\n" name;
4931            pr "  bool %s;\n" n;
4932            pr "};\n\n"
4933        | RConstString _ | RConstOptString _ ->
4934            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
4935        | RString n ->
4936            pr "struct %s_ret {\n" name;
4937            pr "  string %s<>;\n" n;
4938            pr "};\n\n"
4939        | RStringList n ->
4940            pr "struct %s_ret {\n" name;
4941            pr "  str %s<>;\n" n;
4942            pr "};\n\n"
4943        | RStruct (n, typ) ->
4944            pr "struct %s_ret {\n" name;
4945            pr "  guestfs_int_%s %s;\n" typ n;
4946            pr "};\n\n"
4947        | RStructList (n, typ) ->
4948            pr "struct %s_ret {\n" name;
4949            pr "  guestfs_int_%s_list %s;\n" typ n;
4950            pr "};\n\n"
4951        | RHashtable n ->
4952            pr "struct %s_ret {\n" name;
4953            pr "  str %s<>;\n" n;
4954            pr "};\n\n"
4955        | RBufferOut n ->
4956            pr "struct %s_ret {\n" name;
4957            pr "  opaque %s<>;\n" n;
4958            pr "};\n\n"
4959       );
4960   ) daemon_functions;
4961
4962   (* Table of procedure numbers. *)
4963   pr "enum guestfs_procedure {\n";
4964   List.iter (
4965     fun (shortname, _, proc_nr, _, _, _, _) ->
4966       pr "  GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
4967   ) daemon_functions;
4968   pr "  GUESTFS_PROC_NR_PROCS\n";
4969   pr "};\n";
4970   pr "\n";
4971
4972   (* Having to choose a maximum message size is annoying for several
4973    * reasons (it limits what we can do in the API), but it (a) makes
4974    * the protocol a lot simpler, and (b) provides a bound on the size
4975    * of the daemon which operates in limited memory space.  For large
4976    * file transfers you should use FTP.
4977    *)
4978   pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
4979   pr "\n";
4980
4981   (* Message header, etc. *)
4982   pr "\
4983 /* The communication protocol is now documented in the guestfs(3)
4984  * manpage.
4985  */
4986
4987 const GUESTFS_PROGRAM = 0x2000F5F5;
4988 const GUESTFS_PROTOCOL_VERSION = 1;
4989
4990 /* These constants must be larger than any possible message length. */
4991 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
4992 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
4993
4994 enum guestfs_message_direction {
4995   GUESTFS_DIRECTION_CALL = 0,        /* client -> daemon */
4996   GUESTFS_DIRECTION_REPLY = 1        /* daemon -> client */
4997 };
4998
4999 enum guestfs_message_status {
5000   GUESTFS_STATUS_OK = 0,
5001   GUESTFS_STATUS_ERROR = 1
5002 };
5003
5004 const GUESTFS_ERROR_LEN = 256;
5005
5006 struct guestfs_message_error {
5007   string error_message<GUESTFS_ERROR_LEN>;
5008 };
5009
5010 struct guestfs_message_header {
5011   unsigned prog;                     /* GUESTFS_PROGRAM */
5012   unsigned vers;                     /* GUESTFS_PROTOCOL_VERSION */
5013   guestfs_procedure proc;            /* GUESTFS_PROC_x */
5014   guestfs_message_direction direction;
5015   unsigned serial;                   /* message serial number */
5016   guestfs_message_status status;
5017 };
5018
5019 const GUESTFS_MAX_CHUNK_SIZE = 8192;
5020
5021 struct guestfs_chunk {
5022   int cancel;                        /* if non-zero, transfer is cancelled */
5023   /* data size is 0 bytes if the transfer has finished successfully */
5024   opaque data<GUESTFS_MAX_CHUNK_SIZE>;
5025 };
5026 "
5027
5028 (* Generate the guestfs-structs.h file. *)
5029 and generate_structs_h () =
5030   generate_header CStyle LGPLv2;
5031
5032   (* This is a public exported header file containing various
5033    * structures.  The structures are carefully written to have
5034    * exactly the same in-memory format as the XDR structures that
5035    * we use on the wire to the daemon.  The reason for creating
5036    * copies of these structures here is just so we don't have to
5037    * export the whole of guestfs_protocol.h (which includes much
5038    * unrelated and XDR-dependent stuff that we don't want to be
5039    * public, or required by clients).
5040    *
5041    * To reiterate, we will pass these structures to and from the
5042    * client with a simple assignment or memcpy, so the format
5043    * must be identical to what rpcgen / the RFC defines.
5044    *)
5045
5046   (* Public structures. *)
5047   List.iter (
5048     fun (typ, cols) ->
5049       pr "struct guestfs_%s {\n" typ;
5050       List.iter (
5051         function
5052         | name, FChar -> pr "  char %s;\n" name
5053         | name, FString -> pr "  char *%s;\n" name
5054         | name, FBuffer ->
5055             pr "  uint32_t %s_len;\n" name;
5056             pr "  char *%s;\n" name
5057         | name, FUUID -> pr "  char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
5058         | name, FUInt32 -> pr "  uint32_t %s;\n" name
5059         | name, FInt32 -> pr "  int32_t %s;\n" name
5060         | name, (FUInt64|FBytes) -> pr "  uint64_t %s;\n" name
5061         | name, FInt64 -> pr "  int64_t %s;\n" name
5062         | name, FOptPercent -> pr "  float %s; /* [0..100] or -1 */\n" name
5063       ) cols;
5064       pr "};\n";
5065       pr "\n";
5066       pr "struct guestfs_%s_list {\n" typ;
5067       pr "  uint32_t len;\n";
5068       pr "  struct guestfs_%s *val;\n" typ;
5069       pr "};\n";
5070       pr "\n";
5071       pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
5072       pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
5073       pr "\n"
5074   ) structs
5075
5076 (* Generate the guestfs-actions.h file. *)
5077 and generate_actions_h () =
5078   generate_header CStyle LGPLv2;
5079   List.iter (
5080     fun (shortname, style, _, _, _, _, _) ->
5081       let name = "guestfs_" ^ shortname in
5082       generate_prototype ~single_line:true ~newline:true ~handle:"handle"
5083         name style
5084   ) all_functions
5085
5086 (* Generate the guestfs-internal-actions.h file. *)
5087 and generate_internal_actions_h () =
5088   generate_header CStyle LGPLv2;
5089   List.iter (
5090     fun (shortname, style, _, _, _, _, _) ->
5091       let name = "guestfs__" ^ shortname in
5092       generate_prototype ~single_line:true ~newline:true ~handle:"handle"
5093         name style
5094   ) non_daemon_functions
5095
5096 (* Generate the client-side dispatch stubs. *)
5097 and generate_client_actions () =
5098   generate_header CStyle LGPLv2;
5099
5100   pr "\
5101 #include <stdio.h>
5102 #include <stdlib.h>
5103 #include <stdint.h>
5104 #include <inttypes.h>
5105
5106 #include \"guestfs.h\"
5107 #include \"guestfs-internal.h\"
5108 #include \"guestfs-internal-actions.h\"
5109 #include \"guestfs_protocol.h\"
5110
5111 #define error guestfs_error
5112 //#define perrorf guestfs_perrorf
5113 #define safe_malloc guestfs_safe_malloc
5114 #define safe_realloc guestfs_safe_realloc
5115 //#define safe_strdup guestfs_safe_strdup
5116 #define safe_memdup guestfs_safe_memdup
5117
5118 /* Check the return message from a call for validity. */
5119 static int
5120 check_reply_header (guestfs_h *g,
5121                     const struct guestfs_message_header *hdr,
5122                     unsigned int proc_nr, unsigned int serial)
5123 {
5124   if (hdr->prog != GUESTFS_PROGRAM) {
5125     error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
5126     return -1;
5127   }
5128   if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
5129     error (g, \"wrong protocol version (%%d/%%d)\",
5130            hdr->vers, GUESTFS_PROTOCOL_VERSION);
5131     return -1;
5132   }
5133   if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
5134     error (g, \"unexpected message direction (%%d/%%d)\",
5135            hdr->direction, GUESTFS_DIRECTION_REPLY);
5136     return -1;
5137   }
5138   if (hdr->proc != proc_nr) {
5139     error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
5140     return -1;
5141   }
5142   if (hdr->serial != serial) {
5143     error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
5144     return -1;
5145   }
5146
5147   return 0;
5148 }
5149
5150 /* Check we are in the right state to run a high-level action. */
5151 static int
5152 check_state (guestfs_h *g, const char *caller)
5153 {
5154   if (!guestfs__is_ready (g)) {
5155     if (guestfs__is_config (g) || guestfs__is_launching (g))
5156       error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
5157         caller);
5158     else
5159       error (g, \"%%s called from the wrong state, %%d != READY\",
5160         caller, guestfs__get_state (g));
5161     return -1;
5162   }
5163   return 0;
5164 }
5165
5166 ";
5167
5168   (* Generate code to generate guestfish call traces. *)
5169   let trace_call shortname style =
5170     pr "  if (guestfs__get_trace (g)) {\n";
5171
5172     let needs_i =
5173       List.exists (function
5174                    | StringList _ | DeviceList _ -> true
5175                    | _ -> false) (snd style) in
5176     if needs_i then (
5177       pr "    int i;\n";
5178       pr "\n"
5179     );
5180
5181     pr "    printf (\"%s\");\n" shortname;
5182     List.iter (
5183       function
5184       | String n                        (* strings *)
5185       | Device n
5186       | Pathname n
5187       | Dev_or_Path n
5188       | FileIn n
5189       | FileOut n ->
5190           (* guestfish doesn't support string escaping, so neither do we *)
5191           pr "    printf (\" \\\"%%s\\\"\", %s);\n" n
5192       | OptString n ->                  (* string option *)
5193           pr "    if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
5194           pr "    else printf (\" null\");\n"
5195       | StringList n
5196       | DeviceList n ->                 (* string list *)
5197           pr "    putchar (' ');\n";
5198           pr "    putchar ('\"');\n";
5199           pr "    for (i = 0; %s[i]; ++i) {\n" n;
5200           pr "      if (i > 0) putchar (' ');\n";
5201           pr "      fputs (%s[i], stdout);\n" n;
5202           pr "    }\n";
5203           pr "    putchar ('\"');\n";
5204       | Bool n ->                       (* boolean *)
5205           pr "    fputs (%s ? \" true\" : \" false\", stdout);\n" n
5206       | Int n ->                        (* int *)
5207           pr "    printf (\" %%d\", %s);\n" n
5208       | Int64 n ->
5209           pr "    printf (\" %%\" PRIi64, %s);\n" n
5210     ) (snd style);
5211     pr "    putchar ('\\n');\n";
5212     pr "  }\n";
5213     pr "\n";
5214   in
5215
5216   (* For non-daemon functions, generate a wrapper around each function. *)
5217   List.iter (
5218     fun (shortname, style, _, _, _, _, _) ->
5219       let name = "guestfs_" ^ shortname in
5220
5221       generate_prototype ~extern:false ~semicolon:false ~newline:true
5222         ~handle:"g" name style;
5223       pr "{\n";
5224       trace_call shortname style;
5225       pr "  return guestfs__%s " shortname;
5226       generate_c_call_args ~handle:"g" style;
5227       pr ";\n";
5228       pr "}\n";
5229       pr "\n"
5230   ) non_daemon_functions;
5231
5232   (* Client-side stubs for each function. *)
5233   List.iter (
5234     fun (shortname, style, _, _, _, _, _) ->
5235       let name = "guestfs_" ^ shortname in
5236
5237       (* Generate the action stub. *)
5238       generate_prototype ~extern:false ~semicolon:false ~newline:true
5239         ~handle:"g" name style;
5240
5241       let error_code =
5242         match fst style with
5243         | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
5244         | RConstString _ | RConstOptString _ ->
5245             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5246         | RString _ | RStringList _
5247         | RStruct _ | RStructList _
5248         | RHashtable _ | RBufferOut _ ->
5249             "NULL" in
5250
5251       pr "{\n";
5252
5253       (match snd style with
5254        | [] -> ()
5255        | _ -> pr "  struct %s_args args;\n" name
5256       );
5257
5258       pr "  guestfs_message_header hdr;\n";
5259       pr "  guestfs_message_error err;\n";
5260       let has_ret =
5261         match fst style with
5262         | RErr -> false
5263         | RConstString _ | RConstOptString _ ->
5264             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5265         | RInt _ | RInt64 _
5266         | RBool _ | RString _ | RStringList _
5267         | RStruct _ | RStructList _
5268         | RHashtable _ | RBufferOut _ ->
5269             pr "  struct %s_ret ret;\n" name;
5270             true in
5271
5272       pr "  int serial;\n";
5273       pr "  int r;\n";
5274       pr "\n";
5275       trace_call shortname style;
5276       pr "  if (check_state (g, \"%s\") == -1) return %s;\n" name error_code;
5277       pr "  guestfs___set_busy (g);\n";
5278       pr "\n";
5279
5280       (* Send the main header and arguments. *)
5281       (match snd style with
5282        | [] ->
5283            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
5284              (String.uppercase shortname)
5285        | args ->
5286            List.iter (
5287              function
5288              | Pathname n | Device n | Dev_or_Path n | String n ->
5289                  pr "  args.%s = (char *) %s;\n" n n
5290              | OptString n ->
5291                  pr "  args.%s = %s ? (char **) &%s : NULL;\n" n n n
5292              | StringList n | DeviceList n ->
5293                  pr "  args.%s.%s_val = (char **) %s;\n" n n n;
5294                  pr "  for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
5295              | Bool n ->
5296                  pr "  args.%s = %s;\n" n n
5297              | Int n ->
5298                  pr "  args.%s = %s;\n" n n
5299              | Int64 n ->
5300                  pr "  args.%s = %s;\n" n n
5301              | FileIn _ | FileOut _ -> ()
5302            ) args;
5303            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
5304              (String.uppercase shortname);
5305            pr "        (xdrproc_t) xdr_%s_args, (char *) &args);\n"
5306              name;
5307       );
5308       pr "  if (serial == -1) {\n";
5309       pr "    guestfs___end_busy (g);\n";
5310       pr "    return %s;\n" error_code;
5311       pr "  }\n";
5312       pr "\n";
5313
5314       (* Send any additional files (FileIn) requested. *)
5315       let need_read_reply_label = ref false in
5316       List.iter (
5317         function
5318         | FileIn n ->
5319             pr "  r = guestfs___send_file (g, %s);\n" n;
5320             pr "  if (r == -1) {\n";
5321             pr "    guestfs___end_busy (g);\n";
5322             pr "    return %s;\n" error_code;
5323             pr "  }\n";
5324             pr "  if (r == -2) /* daemon cancelled */\n";
5325             pr "    goto read_reply;\n";
5326             need_read_reply_label := true;
5327             pr "\n";
5328         | _ -> ()
5329       ) (snd style);
5330
5331       (* Wait for the reply from the remote end. *)
5332       if !need_read_reply_label then pr " read_reply:\n";
5333       pr "  memset (&hdr, 0, sizeof hdr);\n";
5334       pr "  memset (&err, 0, sizeof err);\n";
5335       if has_ret then pr "  memset (&ret, 0, sizeof ret);\n";
5336       pr "\n";
5337       pr "  r = guestfs___recv (g, \"%s\", &hdr, &err,\n        " shortname;
5338       if not has_ret then
5339         pr "NULL, NULL"
5340       else
5341         pr "(xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret" shortname;
5342       pr ");\n";
5343
5344       pr "  if (r == -1) {\n";
5345       pr "    guestfs___end_busy (g);\n";
5346       pr "    return %s;\n" error_code;
5347       pr "  }\n";
5348       pr "\n";
5349
5350       pr "  if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
5351         (String.uppercase shortname);
5352       pr "    guestfs___end_busy (g);\n";
5353       pr "    return %s;\n" error_code;
5354       pr "  }\n";
5355       pr "\n";
5356
5357       pr "  if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
5358       pr "    error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
5359       pr "    free (err.error_message);\n";
5360       pr "    guestfs___end_busy (g);\n";
5361       pr "    return %s;\n" error_code;
5362       pr "  }\n";
5363       pr "\n";
5364
5365       (* Expecting to receive further files (FileOut)? *)
5366       List.iter (
5367         function
5368         | FileOut n ->
5369             pr "  if (guestfs___recv_file (g, %s) == -1) {\n" n;
5370             pr "    guestfs___end_busy (g);\n";
5371             pr "    return %s;\n" error_code;
5372             pr "  }\n";
5373             pr "\n";
5374         | _ -> ()
5375       ) (snd style);
5376
5377       pr "  guestfs___end_busy (g);\n";
5378
5379       (match fst style with
5380        | RErr -> pr "  return 0;\n"
5381        | RInt n | RInt64 n | RBool n ->
5382            pr "  return ret.%s;\n" n
5383        | RConstString _ | RConstOptString _ ->
5384            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5385        | RString n ->
5386            pr "  return ret.%s; /* caller will free */\n" n
5387        | RStringList n | RHashtable n ->
5388            pr "  /* caller will free this, but we need to add a NULL entry */\n";
5389            pr "  ret.%s.%s_val =\n" n n;
5390            pr "    safe_realloc (g, ret.%s.%s_val,\n" n n;
5391            pr "                  sizeof (char *) * (ret.%s.%s_len + 1));\n"
5392              n n;
5393            pr "  ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
5394            pr "  return ret.%s.%s_val;\n" n n
5395        | RStruct (n, _) ->
5396            pr "  /* caller will free this */\n";
5397            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5398        | RStructList (n, _) ->
5399            pr "  /* caller will free this */\n";
5400            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5401        | RBufferOut n ->
5402            pr "  /* RBufferOut is tricky: If the buffer is zero-length, then\n";
5403            pr "   * _val might be NULL here.  To make the API saner for\n";
5404            pr "   * callers, we turn this case into a unique pointer (using\n";
5405            pr "   * malloc(1)).\n";
5406            pr "   */\n";
5407            pr "  if (ret.%s.%s_len > 0) {\n" n n;
5408            pr "    *size_r = ret.%s.%s_len;\n" n n;
5409            pr "    return ret.%s.%s_val; /* caller will free */\n" n n;
5410            pr "  } else {\n";
5411            pr "    free (ret.%s.%s_val);\n" n n;
5412            pr "    char *p = safe_malloc (g, 1);\n";
5413            pr "    *size_r = ret.%s.%s_len;\n" n n;
5414            pr "    return p;\n";
5415            pr "  }\n";
5416       );
5417
5418       pr "}\n\n"
5419   ) daemon_functions;
5420
5421   (* Functions to free structures. *)
5422   pr "/* Structure-freeing functions.  These rely on the fact that the\n";
5423   pr " * structure format is identical to the XDR format.  See note in\n";
5424   pr " * generator.ml.\n";
5425   pr " */\n";
5426   pr "\n";
5427
5428   List.iter (
5429     fun (typ, _) ->
5430       pr "void\n";
5431       pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
5432       pr "{\n";
5433       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
5434       pr "  free (x);\n";
5435       pr "}\n";
5436       pr "\n";
5437
5438       pr "void\n";
5439       pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
5440       pr "{\n";
5441       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
5442       pr "  free (x);\n";
5443       pr "}\n";
5444       pr "\n";
5445
5446   ) structs;
5447
5448 (* Generate daemon/actions.h. *)
5449 and generate_daemon_actions_h () =
5450   generate_header CStyle GPLv2;
5451
5452   pr "#include \"../src/guestfs_protocol.h\"\n";
5453   pr "\n";
5454
5455   List.iter (
5456     fun (name, style, _, _, _, _, _) ->
5457       generate_prototype
5458         ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
5459         name style;
5460   ) daemon_functions
5461
5462 (* Generate the server-side stubs. *)
5463 and generate_daemon_actions () =
5464   generate_header CStyle GPLv2;
5465
5466   pr "#include <config.h>\n";
5467   pr "\n";
5468   pr "#include <stdio.h>\n";
5469   pr "#include <stdlib.h>\n";
5470   pr "#include <string.h>\n";
5471   pr "#include <inttypes.h>\n";
5472   pr "#include <rpc/types.h>\n";
5473   pr "#include <rpc/xdr.h>\n";
5474   pr "\n";
5475   pr "#include \"daemon.h\"\n";
5476   pr "#include \"c-ctype.h\"\n";
5477   pr "#include \"../src/guestfs_protocol.h\"\n";
5478   pr "#include \"actions.h\"\n";
5479   pr "\n";
5480
5481   List.iter (
5482     fun (name, style, _, _, _, _, _) ->
5483       (* Generate server-side stubs. *)
5484       pr "static void %s_stub (XDR *xdr_in)\n" name;
5485       pr "{\n";
5486       let error_code =
5487         match fst style with
5488         | RErr | RInt _ -> pr "  int r;\n"; "-1"
5489         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
5490         | RBool _ -> pr "  int r;\n"; "-1"
5491         | RConstString _ | RConstOptString _ ->
5492             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5493         | RString _ -> pr "  char *r;\n"; "NULL"
5494         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
5495         | RStruct (_, typ) -> pr "  guestfs_int_%s *r;\n" typ; "NULL"
5496         | RStructList (_, typ) -> pr "  guestfs_int_%s_list *r;\n" typ; "NULL"
5497         | RBufferOut _ ->
5498             pr "  size_t size = 1;\n";
5499             pr "  char *r;\n";
5500             "NULL" in
5501
5502       (match snd style with
5503        | [] -> ()
5504        | args ->
5505            pr "  struct guestfs_%s_args args;\n" name;
5506            List.iter (
5507              function
5508              | Device n | Dev_or_Path n
5509              | Pathname n
5510              | String n -> ()
5511              | OptString n -> pr "  char *%s;\n" n
5512              | StringList n | DeviceList n -> pr "  char **%s;\n" n
5513              | Bool n -> pr "  int %s;\n" n
5514              | Int n -> pr "  int %s;\n" n
5515              | Int64 n -> pr "  int64_t %s;\n" n
5516              | FileIn _ | FileOut _ -> ()
5517            ) args
5518       );
5519       pr "\n";
5520
5521       (match snd style with
5522        | [] -> ()
5523        | args ->
5524            pr "  memset (&args, 0, sizeof args);\n";
5525            pr "\n";
5526            pr "  if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
5527            pr "    reply_with_error (\"%%s: daemon failed to decode procedure arguments\", \"%s\");\n" name;
5528            pr "    return;\n";
5529            pr "  }\n";
5530            let pr_args n =
5531              pr "  char *%s = args.%s;\n" n n
5532            in
5533            let pr_list_handling_code n =
5534              pr "  %s = realloc (args.%s.%s_val,\n" n n n;
5535              pr "                sizeof (char *) * (args.%s.%s_len+1));\n" n n;
5536              pr "  if (%s == NULL) {\n" n;
5537              pr "    reply_with_perror (\"realloc\");\n";
5538              pr "    goto done;\n";
5539              pr "  }\n";
5540              pr "  %s[args.%s.%s_len] = NULL;\n" n n n;
5541              pr "  args.%s.%s_val = %s;\n" n n n;
5542            in
5543            List.iter (
5544              function
5545              | Pathname n ->
5546                  pr_args n;
5547                  pr "  ABS_PATH (%s, goto done);\n" n;
5548              | Device n ->
5549                  pr_args n;
5550                  pr "  RESOLVE_DEVICE (%s, goto done);\n" n;
5551              | Dev_or_Path n ->
5552                  pr_args n;
5553                  pr "  REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, goto done);\n" n;
5554              | String n -> pr_args n
5555              | OptString n -> pr "  %s = args.%s ? *args.%s : NULL;\n" n n n
5556              | StringList n ->
5557                  pr_list_handling_code n;
5558              | DeviceList n ->
5559                  pr_list_handling_code n;
5560                  pr "  /* Ensure that each is a device,\n";
5561                  pr "   * and perform device name translation. */\n";
5562                  pr "  { int pvi; for (pvi = 0; physvols[pvi] != NULL; ++pvi)\n";
5563                  pr "    RESOLVE_DEVICE (physvols[pvi], goto done);\n";
5564                  pr "  }\n";
5565              | Bool n -> pr "  %s = args.%s;\n" n n
5566              | Int n -> pr "  %s = args.%s;\n" n n
5567              | Int64 n -> pr "  %s = args.%s;\n" n n
5568              | FileIn _ | FileOut _ -> ()
5569            ) args;
5570            pr "\n"
5571       );
5572
5573
5574       (* this is used at least for do_equal *)
5575       if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
5576         (* Emit NEED_ROOT just once, even when there are two or
5577            more Pathname args *)
5578         pr "  NEED_ROOT (goto done);\n";
5579       );
5580
5581       (* Don't want to call the impl with any FileIn or FileOut
5582        * parameters, since these go "outside" the RPC protocol.
5583        *)
5584       let args' =
5585         List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
5586           (snd style) in
5587       pr "  r = do_%s " name;
5588       generate_c_call_args (fst style, args');
5589       pr ";\n";
5590
5591       (match fst style with
5592        | RErr | RInt _ | RInt64 _ | RBool _
5593        | RConstString _ | RConstOptString _
5594        | RString _ | RStringList _ | RHashtable _
5595        | RStruct (_, _) | RStructList (_, _) ->
5596            pr "  if (r == %s)\n" error_code;
5597            pr "    /* do_%s has already called reply_with_error */\n" name;
5598            pr "    goto done;\n";
5599            pr "\n"
5600        | RBufferOut _ ->
5601            pr "  /* size == 0 && r == NULL could be a non-error case (just\n";
5602            pr "   * an ordinary zero-length buffer), so be careful ...\n";
5603            pr "   */\n";
5604            pr "  if (size == 1 && r == %s)\n" error_code;
5605            pr "    /* do_%s has already called reply_with_error */\n" name;
5606            pr "    goto done;\n";
5607            pr "\n"
5608       );
5609
5610       (* If there are any FileOut parameters, then the impl must
5611        * send its own reply.
5612        *)
5613       let no_reply =
5614         List.exists (function FileOut _ -> true | _ -> false) (snd style) in
5615       if no_reply then
5616         pr "  /* do_%s has already sent a reply */\n" name
5617       else (
5618         match fst style with
5619         | RErr -> pr "  reply (NULL, NULL);\n"
5620         | RInt n | RInt64 n | RBool n ->
5621             pr "  struct guestfs_%s_ret ret;\n" name;
5622             pr "  ret.%s = r;\n" n;
5623             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5624               name
5625         | RConstString _ | RConstOptString _ ->
5626             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5627         | RString n ->
5628             pr "  struct guestfs_%s_ret ret;\n" name;
5629             pr "  ret.%s = r;\n" n;
5630             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5631               name;
5632             pr "  free (r);\n"
5633         | RStringList n | RHashtable n ->
5634             pr "  struct guestfs_%s_ret ret;\n" name;
5635             pr "  ret.%s.%s_len = count_strings (r);\n" n n;
5636             pr "  ret.%s.%s_val = r;\n" n n;
5637             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5638               name;
5639             pr "  free_strings (r);\n"
5640         | RStruct (n, _) ->
5641             pr "  struct guestfs_%s_ret ret;\n" name;
5642             pr "  ret.%s = *r;\n" n;
5643             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5644               name;
5645             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5646               name
5647         | RStructList (n, _) ->
5648             pr "  struct guestfs_%s_ret ret;\n" name;
5649             pr "  ret.%s = *r;\n" n;
5650             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5651               name;
5652             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5653               name
5654         | RBufferOut n ->
5655             pr "  struct guestfs_%s_ret ret;\n" name;
5656             pr "  ret.%s.%s_val = r;\n" n n;
5657             pr "  ret.%s.%s_len = size;\n" n n;
5658             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5659               name;
5660             pr "  free (r);\n"
5661       );
5662
5663       (* Free the args. *)
5664       (match snd style with
5665        | [] ->
5666            pr "done: ;\n";
5667        | _ ->
5668            pr "done:\n";
5669            pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
5670              name
5671       );
5672
5673       pr "}\n\n";
5674   ) daemon_functions;
5675
5676   (* Dispatch function. *)
5677   pr "void dispatch_incoming_message (XDR *xdr_in)\n";
5678   pr "{\n";
5679   pr "  switch (proc_nr) {\n";
5680
5681   List.iter (
5682     fun (name, style, _, _, _, _, _) ->
5683       pr "    case GUESTFS_PROC_%s:\n" (String.uppercase name);
5684       pr "      %s_stub (xdr_in);\n" name;
5685       pr "      break;\n"
5686   ) daemon_functions;
5687
5688   pr "    default:\n";
5689   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";
5690   pr "  }\n";
5691   pr "}\n";
5692   pr "\n";
5693
5694   (* LVM columns and tokenization functions. *)
5695   (* XXX This generates crap code.  We should rethink how we
5696    * do this parsing.
5697    *)
5698   List.iter (
5699     function
5700     | typ, cols ->
5701         pr "static const char *lvm_%s_cols = \"%s\";\n"
5702           typ (String.concat "," (List.map fst cols));
5703         pr "\n";
5704
5705         pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
5706         pr "{\n";
5707         pr "  char *tok, *p, *next;\n";
5708         pr "  int i, j;\n";
5709         pr "\n";
5710         (*
5711           pr "  fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
5712           pr "\n";
5713         *)
5714         pr "  if (!str) {\n";
5715         pr "    fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
5716         pr "    return -1;\n";
5717         pr "  }\n";
5718         pr "  if (!*str || c_isspace (*str)) {\n";
5719         pr "    fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
5720         pr "    return -1;\n";
5721         pr "  }\n";
5722         pr "  tok = str;\n";
5723         List.iter (
5724           fun (name, coltype) ->
5725             pr "  if (!tok) {\n";
5726             pr "    fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
5727             pr "    return -1;\n";
5728             pr "  }\n";
5729             pr "  p = strchrnul (tok, ',');\n";
5730             pr "  if (*p) next = p+1; else next = NULL;\n";
5731             pr "  *p = '\\0';\n";
5732             (match coltype with
5733              | FString ->
5734                  pr "  r->%s = strdup (tok);\n" name;
5735                  pr "  if (r->%s == NULL) {\n" name;
5736                  pr "    perror (\"strdup\");\n";
5737                  pr "    return -1;\n";
5738                  pr "  }\n"
5739              | FUUID ->
5740                  pr "  for (i = j = 0; i < 32; ++j) {\n";
5741                  pr "    if (tok[j] == '\\0') {\n";
5742                  pr "      fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
5743                  pr "      return -1;\n";
5744                  pr "    } else if (tok[j] != '-')\n";
5745                  pr "      r->%s[i++] = tok[j];\n" name;
5746                  pr "  }\n";
5747              | FBytes ->
5748                  pr "  if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
5749                  pr "    fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
5750                  pr "    return -1;\n";
5751                  pr "  }\n";
5752              | FInt64 ->
5753                  pr "  if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
5754                  pr "    fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
5755                  pr "    return -1;\n";
5756                  pr "  }\n";
5757              | FOptPercent ->
5758                  pr "  if (tok[0] == '\\0')\n";
5759                  pr "    r->%s = -1;\n" name;
5760                  pr "  else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
5761                  pr "    fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
5762                  pr "    return -1;\n";
5763                  pr "  }\n";
5764              | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
5765                  assert false (* can never be an LVM column *)
5766             );
5767             pr "  tok = next;\n";
5768         ) cols;
5769
5770         pr "  if (tok != NULL) {\n";
5771         pr "    fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
5772         pr "    return -1;\n";
5773         pr "  }\n";
5774         pr "  return 0;\n";
5775         pr "}\n";
5776         pr "\n";
5777
5778         pr "guestfs_int_lvm_%s_list *\n" typ;
5779         pr "parse_command_line_%ss (void)\n" typ;
5780         pr "{\n";
5781         pr "  char *out, *err;\n";
5782         pr "  char *p, *pend;\n";
5783         pr "  int r, i;\n";
5784         pr "  guestfs_int_lvm_%s_list *ret;\n" typ;
5785         pr "  void *newp;\n";
5786         pr "\n";
5787         pr "  ret = malloc (sizeof *ret);\n";
5788         pr "  if (!ret) {\n";
5789         pr "    reply_with_perror (\"malloc\");\n";
5790         pr "    return NULL;\n";
5791         pr "  }\n";
5792         pr "\n";
5793         pr "  ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
5794         pr "  ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
5795         pr "\n";
5796         pr "  r = command (&out, &err,\n";
5797         pr "           \"/sbin/lvm\", \"%ss\",\n" typ;
5798         pr "           \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
5799         pr "           \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
5800         pr "  if (r == -1) {\n";
5801         pr "    reply_with_error (\"%%s\", err);\n";
5802         pr "    free (out);\n";
5803         pr "    free (err);\n";
5804         pr "    free (ret);\n";
5805         pr "    return NULL;\n";
5806         pr "  }\n";
5807         pr "\n";
5808         pr "  free (err);\n";
5809         pr "\n";
5810         pr "  /* Tokenize each line of the output. */\n";
5811         pr "  p = out;\n";
5812         pr "  i = 0;\n";
5813         pr "  while (p) {\n";
5814         pr "    pend = strchr (p, '\\n');       /* Get the next line of output. */\n";
5815         pr "    if (pend) {\n";
5816         pr "      *pend = '\\0';\n";
5817         pr "      pend++;\n";
5818         pr "    }\n";
5819         pr "\n";
5820         pr "    while (*p && c_isspace (*p))    /* Skip any leading whitespace. */\n";
5821         pr "      p++;\n";
5822         pr "\n";
5823         pr "    if (!*p) {                      /* Empty line?  Skip it. */\n";
5824         pr "      p = pend;\n";
5825         pr "      continue;\n";
5826         pr "    }\n";
5827         pr "\n";
5828         pr "    /* Allocate some space to store this next entry. */\n";
5829         pr "    newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
5830         pr "                sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
5831         pr "    if (newp == NULL) {\n";
5832         pr "      reply_with_perror (\"realloc\");\n";
5833         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
5834         pr "      free (ret);\n";
5835         pr "      free (out);\n";
5836         pr "      return NULL;\n";
5837         pr "    }\n";
5838         pr "    ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
5839         pr "\n";
5840         pr "    /* Tokenize the next entry. */\n";
5841         pr "    r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
5842         pr "    if (r == -1) {\n";
5843         pr "      reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
5844         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
5845         pr "      free (ret);\n";
5846         pr "      free (out);\n";
5847         pr "      return NULL;\n";
5848         pr "    }\n";
5849         pr "\n";
5850         pr "    ++i;\n";
5851         pr "    p = pend;\n";
5852         pr "  }\n";
5853         pr "\n";
5854         pr "  ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
5855         pr "\n";
5856         pr "  free (out);\n";
5857         pr "  return ret;\n";
5858         pr "}\n"
5859
5860   ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
5861
5862 (* Generate a list of function names, for debugging in the daemon.. *)
5863 and generate_daemon_names () =
5864   generate_header CStyle GPLv2;
5865
5866   pr "#include <config.h>\n";
5867   pr "\n";
5868   pr "#include \"daemon.h\"\n";
5869   pr "\n";
5870
5871   pr "/* This array is indexed by proc_nr.  See guestfs_protocol.x. */\n";
5872   pr "const char *function_names[] = {\n";
5873   List.iter (
5874     fun (name, _, proc_nr, _, _, _, _) -> pr "  [%d] = \"%s\",\n" proc_nr name
5875   ) daemon_functions;
5876   pr "};\n";
5877
5878 (* Generate the tests. *)
5879 and generate_tests () =
5880   generate_header CStyle GPLv2;
5881
5882   pr "\
5883 #include <stdio.h>
5884 #include <stdlib.h>
5885 #include <string.h>
5886 #include <unistd.h>
5887 #include <sys/types.h>
5888 #include <fcntl.h>
5889
5890 #include \"guestfs.h\"
5891 #include \"guestfs-internal.h\"
5892
5893 static guestfs_h *g;
5894 static int suppress_error = 0;
5895
5896 static void print_error (guestfs_h *g, void *data, const char *msg)
5897 {
5898   if (!suppress_error)
5899     fprintf (stderr, \"%%s\\n\", msg);
5900 }
5901
5902 /* FIXME: nearly identical code appears in fish.c */
5903 static void print_strings (char *const *argv)
5904 {
5905   int argc;
5906
5907   for (argc = 0; argv[argc] != NULL; ++argc)
5908     printf (\"\\t%%s\\n\", argv[argc]);
5909 }
5910
5911 /*
5912 static void print_table (char const *const *argv)
5913 {
5914   int i;
5915
5916   for (i = 0; argv[i] != NULL; i += 2)
5917     printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
5918 }
5919 */
5920
5921 ";
5922
5923   (* Generate a list of commands which are not tested anywhere. *)
5924   pr "static void no_test_warnings (void)\n";
5925   pr "{\n";
5926
5927   let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
5928   List.iter (
5929     fun (_, _, _, _, tests, _, _) ->
5930       let tests = filter_map (
5931         function
5932         | (_, (Always|If _|Unless _), test) -> Some test
5933         | (_, Disabled, _) -> None
5934       ) tests in
5935       let seq = List.concat (List.map seq_of_test tests) in
5936       let cmds_tested = List.map List.hd seq in
5937       List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
5938   ) all_functions;
5939
5940   List.iter (
5941     fun (name, _, _, _, _, _, _) ->
5942       if not (Hashtbl.mem hash name) then
5943         pr "  fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
5944   ) all_functions;
5945
5946   pr "}\n";
5947   pr "\n";
5948
5949   (* Generate the actual tests.  Note that we generate the tests
5950    * in reverse order, deliberately, so that (in general) the
5951    * newest tests run first.  This makes it quicker and easier to
5952    * debug them.
5953    *)
5954   let test_names =
5955     List.map (
5956       fun (name, _, _, _, tests, _, _) ->
5957         mapi (generate_one_test name) tests
5958     ) (List.rev all_functions) in
5959   let test_names = List.concat test_names in
5960   let nr_tests = List.length test_names in
5961
5962   pr "\
5963 int main (int argc, char *argv[])
5964 {
5965   char c = 0;
5966   unsigned long int n_failed = 0;
5967   const char *filename;
5968   int fd;
5969   int nr_tests, test_num = 0;
5970
5971   setbuf (stdout, NULL);
5972
5973   no_test_warnings ();
5974
5975   g = guestfs_create ();
5976   if (g == NULL) {
5977     printf (\"guestfs_create FAILED\\n\");
5978     exit (1);
5979   }
5980
5981   guestfs_set_error_handler (g, print_error, NULL);
5982
5983   guestfs_set_path (g, \"../appliance\");
5984
5985   filename = \"test1.img\";
5986   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
5987   if (fd == -1) {
5988     perror (filename);
5989     exit (1);
5990   }
5991   if (lseek (fd, %d, SEEK_SET) == -1) {
5992     perror (\"lseek\");
5993     close (fd);
5994     unlink (filename);
5995     exit (1);
5996   }
5997   if (write (fd, &c, 1) == -1) {
5998     perror (\"write\");
5999     close (fd);
6000     unlink (filename);
6001     exit (1);
6002   }
6003   if (close (fd) == -1) {
6004     perror (filename);
6005     unlink (filename);
6006     exit (1);
6007   }
6008   if (guestfs_add_drive (g, filename) == -1) {
6009     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6010     exit (1);
6011   }
6012
6013   filename = \"test2.img\";
6014   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6015   if (fd == -1) {
6016     perror (filename);
6017     exit (1);
6018   }
6019   if (lseek (fd, %d, SEEK_SET) == -1) {
6020     perror (\"lseek\");
6021     close (fd);
6022     unlink (filename);
6023     exit (1);
6024   }
6025   if (write (fd, &c, 1) == -1) {
6026     perror (\"write\");
6027     close (fd);
6028     unlink (filename);
6029     exit (1);
6030   }
6031   if (close (fd) == -1) {
6032     perror (filename);
6033     unlink (filename);
6034     exit (1);
6035   }
6036   if (guestfs_add_drive (g, filename) == -1) {
6037     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6038     exit (1);
6039   }
6040
6041   filename = \"test3.img\";
6042   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6043   if (fd == -1) {
6044     perror (filename);
6045     exit (1);
6046   }
6047   if (lseek (fd, %d, SEEK_SET) == -1) {
6048     perror (\"lseek\");
6049     close (fd);
6050     unlink (filename);
6051     exit (1);
6052   }
6053   if (write (fd, &c, 1) == -1) {
6054     perror (\"write\");
6055     close (fd);
6056     unlink (filename);
6057     exit (1);
6058   }
6059   if (close (fd) == -1) {
6060     perror (filename);
6061     unlink (filename);
6062     exit (1);
6063   }
6064   if (guestfs_add_drive (g, filename) == -1) {
6065     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6066     exit (1);
6067   }
6068
6069   if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
6070     printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
6071     exit (1);
6072   }
6073
6074   if (guestfs_launch (g) == -1) {
6075     printf (\"guestfs_launch FAILED\\n\");
6076     exit (1);
6077   }
6078
6079   /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
6080   alarm (600);
6081
6082   /* Cancel previous alarm. */
6083   alarm (0);
6084
6085   nr_tests = %d;
6086
6087 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
6088
6089   iteri (
6090     fun i test_name ->
6091       pr "  test_num++;\n";
6092       pr "  printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
6093       pr "  if (%s () == -1) {\n" test_name;
6094       pr "    printf (\"%s FAILED\\n\");\n" test_name;
6095       pr "    n_failed++;\n";
6096       pr "  }\n";
6097   ) test_names;
6098   pr "\n";
6099
6100   pr "  guestfs_close (g);\n";
6101   pr "  unlink (\"test1.img\");\n";
6102   pr "  unlink (\"test2.img\");\n";
6103   pr "  unlink (\"test3.img\");\n";
6104   pr "\n";
6105
6106   pr "  if (n_failed > 0) {\n";
6107   pr "    printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
6108   pr "    exit (1);\n";
6109   pr "  }\n";
6110   pr "\n";
6111
6112   pr "  exit (0);\n";
6113   pr "}\n"
6114
6115 and generate_one_test name i (init, prereq, test) =
6116   let test_name = sprintf "test_%s_%d" name i in
6117
6118   pr "\
6119 static int %s_skip (void)
6120 {
6121   const char *str;
6122
6123   str = getenv (\"TEST_ONLY\");
6124   if (str)
6125     return strstr (str, \"%s\") == NULL;
6126   str = getenv (\"SKIP_%s\");
6127   if (str && STREQ (str, \"1\")) return 1;
6128   str = getenv (\"SKIP_TEST_%s\");
6129   if (str && STREQ (str, \"1\")) return 1;
6130   return 0;
6131 }
6132
6133 " test_name name (String.uppercase test_name) (String.uppercase name);
6134
6135   (match prereq with
6136    | Disabled | Always -> ()
6137    | If code | Unless code ->
6138        pr "static int %s_prereq (void)\n" test_name;
6139        pr "{\n";
6140        pr "  %s\n" code;
6141        pr "}\n";
6142        pr "\n";
6143   );
6144
6145   pr "\
6146 static int %s (void)
6147 {
6148   if (%s_skip ()) {
6149     printf (\"        %%s skipped (reason: environment variable set)\\n\", \"%s\");
6150     return 0;
6151   }
6152
6153 " test_name test_name test_name;
6154
6155   (match prereq with
6156    | Disabled ->
6157        pr "  printf (\"        %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
6158    | If _ ->
6159        pr "  if (! %s_prereq ()) {\n" test_name;
6160        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6161        pr "    return 0;\n";
6162        pr "  }\n";
6163        pr "\n";
6164        generate_one_test_body name i test_name init test;
6165    | Unless _ ->
6166        pr "  if (%s_prereq ()) {\n" test_name;
6167        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6168        pr "    return 0;\n";
6169        pr "  }\n";
6170        pr "\n";
6171        generate_one_test_body name i test_name init test;
6172    | Always ->
6173        generate_one_test_body name i test_name init test
6174   );
6175
6176   pr "  return 0;\n";
6177   pr "}\n";
6178   pr "\n";
6179   test_name
6180
6181 and generate_one_test_body name i test_name init test =
6182   (match init with
6183    | InitNone (* XXX at some point, InitNone and InitEmpty became
6184                * folded together as the same thing.  Really we should
6185                * make InitNone do nothing at all, but the tests may
6186                * need to be checked to make sure this is OK.
6187                *)
6188    | InitEmpty ->
6189        pr "  /* InitNone|InitEmpty for %s */\n" test_name;
6190        List.iter (generate_test_command_call test_name)
6191          [["blockdev_setrw"; "/dev/sda"];
6192           ["umount_all"];
6193           ["lvm_remove_all"]]
6194    | InitPartition ->
6195        pr "  /* InitPartition for %s: create /dev/sda1 */\n" test_name;
6196        List.iter (generate_test_command_call test_name)
6197          [["blockdev_setrw"; "/dev/sda"];
6198           ["umount_all"];
6199           ["lvm_remove_all"];
6200           ["part_disk"; "/dev/sda"; "mbr"]]
6201    | InitBasicFS ->
6202        pr "  /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
6203        List.iter (generate_test_command_call test_name)
6204          [["blockdev_setrw"; "/dev/sda"];
6205           ["umount_all"];
6206           ["lvm_remove_all"];
6207           ["part_disk"; "/dev/sda"; "mbr"];
6208           ["mkfs"; "ext2"; "/dev/sda1"];
6209           ["mount"; "/dev/sda1"; "/"]]
6210    | InitBasicFSonLVM ->
6211        pr "  /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
6212          test_name;
6213        List.iter (generate_test_command_call test_name)
6214          [["blockdev_setrw"; "/dev/sda"];
6215           ["umount_all"];
6216           ["lvm_remove_all"];
6217           ["part_disk"; "/dev/sda"; "mbr"];
6218           ["pvcreate"; "/dev/sda1"];
6219           ["vgcreate"; "VG"; "/dev/sda1"];
6220           ["lvcreate"; "LV"; "VG"; "8"];
6221           ["mkfs"; "ext2"; "/dev/VG/LV"];
6222           ["mount"; "/dev/VG/LV"; "/"]]
6223    | InitISOFS ->
6224        pr "  /* InitISOFS for %s */\n" test_name;
6225        List.iter (generate_test_command_call test_name)
6226          [["blockdev_setrw"; "/dev/sda"];
6227           ["umount_all"];
6228           ["lvm_remove_all"];
6229           ["mount_ro"; "/dev/sdd"; "/"]]
6230   );
6231
6232   let get_seq_last = function
6233     | [] ->
6234         failwithf "%s: you cannot use [] (empty list) when expecting a command"
6235           test_name
6236     | seq ->
6237         let seq = List.rev seq in
6238         List.rev (List.tl seq), List.hd seq
6239   in
6240
6241   match test with
6242   | TestRun seq ->
6243       pr "  /* TestRun for %s (%d) */\n" name i;
6244       List.iter (generate_test_command_call test_name) seq
6245   | TestOutput (seq, expected) ->
6246       pr "  /* TestOutput for %s (%d) */\n" name i;
6247       pr "  const char *expected = \"%s\";\n" (c_quote expected);
6248       let seq, last = get_seq_last seq in
6249       let test () =
6250         pr "    if (STRNEQ (r, expected)) {\n";
6251         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6252         pr "      return -1;\n";
6253         pr "    }\n"
6254       in
6255       List.iter (generate_test_command_call test_name) seq;
6256       generate_test_command_call ~test test_name last
6257   | TestOutputList (seq, expected) ->
6258       pr "  /* TestOutputList for %s (%d) */\n" name i;
6259       let seq, last = get_seq_last seq in
6260       let test () =
6261         iteri (
6262           fun i str ->
6263             pr "    if (!r[%d]) {\n" i;
6264             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6265             pr "      print_strings (r);\n";
6266             pr "      return -1;\n";
6267             pr "    }\n";
6268             pr "    {\n";
6269             pr "      const char *expected = \"%s\";\n" (c_quote str);
6270             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
6271             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6272             pr "        return -1;\n";
6273             pr "      }\n";
6274             pr "    }\n"
6275         ) expected;
6276         pr "    if (r[%d] != NULL) {\n" (List.length expected);
6277         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6278           test_name;
6279         pr "      print_strings (r);\n";
6280         pr "      return -1;\n";
6281         pr "    }\n"
6282       in
6283       List.iter (generate_test_command_call test_name) seq;
6284       generate_test_command_call ~test test_name last
6285   | TestOutputListOfDevices (seq, expected) ->
6286       pr "  /* TestOutputListOfDevices for %s (%d) */\n" name i;
6287       let seq, last = get_seq_last seq in
6288       let test () =
6289         iteri (
6290           fun i str ->
6291             pr "    if (!r[%d]) {\n" i;
6292             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6293             pr "      print_strings (r);\n";
6294             pr "      return -1;\n";
6295             pr "    }\n";
6296             pr "    {\n";
6297             pr "      const char *expected = \"%s\";\n" (c_quote str);
6298             pr "      r[%d][5] = 's';\n" i;
6299             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
6300             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6301             pr "        return -1;\n";
6302             pr "      }\n";
6303             pr "    }\n"
6304         ) expected;
6305         pr "    if (r[%d] != NULL) {\n" (List.length expected);
6306         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6307           test_name;
6308         pr "      print_strings (r);\n";
6309         pr "      return -1;\n";
6310         pr "    }\n"
6311       in
6312       List.iter (generate_test_command_call test_name) seq;
6313       generate_test_command_call ~test test_name last
6314   | TestOutputInt (seq, expected) ->
6315       pr "  /* TestOutputInt for %s (%d) */\n" name i;
6316       let seq, last = get_seq_last seq in
6317       let test () =
6318         pr "    if (r != %d) {\n" expected;
6319         pr "      fprintf (stderr, \"%s: expected %d but got %%d\\n\","
6320           test_name expected;
6321         pr "               (int) r);\n";
6322         pr "      return -1;\n";
6323         pr "    }\n"
6324       in
6325       List.iter (generate_test_command_call test_name) seq;
6326       generate_test_command_call ~test test_name last
6327   | TestOutputIntOp (seq, op, expected) ->
6328       pr "  /* TestOutputIntOp for %s (%d) */\n" name i;
6329       let seq, last = get_seq_last seq in
6330       let test () =
6331         pr "    if (! (r %s %d)) {\n" op expected;
6332         pr "      fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
6333           test_name op expected;
6334         pr "               (int) r);\n";
6335         pr "      return -1;\n";
6336         pr "    }\n"
6337       in
6338       List.iter (generate_test_command_call test_name) seq;
6339       generate_test_command_call ~test test_name last
6340   | TestOutputTrue seq ->
6341       pr "  /* TestOutputTrue for %s (%d) */\n" name i;
6342       let seq, last = get_seq_last seq in
6343       let test () =
6344         pr "    if (!r) {\n";
6345         pr "      fprintf (stderr, \"%s: expected true, got false\\n\");\n"
6346           test_name;
6347         pr "      return -1;\n";
6348         pr "    }\n"
6349       in
6350       List.iter (generate_test_command_call test_name) seq;
6351       generate_test_command_call ~test test_name last
6352   | TestOutputFalse seq ->
6353       pr "  /* TestOutputFalse for %s (%d) */\n" name i;
6354       let seq, last = get_seq_last seq in
6355       let test () =
6356         pr "    if (r) {\n";
6357         pr "      fprintf (stderr, \"%s: expected false, got true\\n\");\n"
6358           test_name;
6359         pr "      return -1;\n";
6360         pr "    }\n"
6361       in
6362       List.iter (generate_test_command_call test_name) seq;
6363       generate_test_command_call ~test test_name last
6364   | TestOutputLength (seq, expected) ->
6365       pr "  /* TestOutputLength for %s (%d) */\n" name i;
6366       let seq, last = get_seq_last seq in
6367       let test () =
6368         pr "    int j;\n";
6369         pr "    for (j = 0; j < %d; ++j)\n" expected;
6370         pr "      if (r[j] == NULL) {\n";
6371         pr "        fprintf (stderr, \"%s: short list returned\\n\");\n"
6372           test_name;
6373         pr "        print_strings (r);\n";
6374         pr "        return -1;\n";
6375         pr "      }\n";
6376         pr "    if (r[j] != NULL) {\n";
6377         pr "      fprintf (stderr, \"%s: long list returned\\n\");\n"
6378           test_name;
6379         pr "      print_strings (r);\n";
6380         pr "      return -1;\n";
6381         pr "    }\n"
6382       in
6383       List.iter (generate_test_command_call test_name) seq;
6384       generate_test_command_call ~test test_name last
6385   | TestOutputBuffer (seq, expected) ->
6386       pr "  /* TestOutputBuffer for %s (%d) */\n" name i;
6387       pr "  const char *expected = \"%s\";\n" (c_quote expected);
6388       let seq, last = get_seq_last seq in
6389       let len = String.length expected in
6390       let test () =
6391         pr "    if (size != %d) {\n" len;
6392         pr "      fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
6393         pr "      return -1;\n";
6394         pr "    }\n";
6395         pr "    if (STRNEQLEN (r, expected, size)) {\n";
6396         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6397         pr "      return -1;\n";
6398         pr "    }\n"
6399       in
6400       List.iter (generate_test_command_call test_name) seq;
6401       generate_test_command_call ~test test_name last
6402   | TestOutputStruct (seq, checks) ->
6403       pr "  /* TestOutputStruct for %s (%d) */\n" name i;
6404       let seq, last = get_seq_last seq in
6405       let test () =
6406         List.iter (
6407           function
6408           | CompareWithInt (field, expected) ->
6409               pr "    if (r->%s != %d) {\n" field expected;
6410               pr "      fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
6411                 test_name field expected;
6412               pr "               (int) r->%s);\n" field;
6413               pr "      return -1;\n";
6414               pr "    }\n"
6415           | CompareWithIntOp (field, op, expected) ->
6416               pr "    if (!(r->%s %s %d)) {\n" field op expected;
6417               pr "      fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
6418                 test_name field op expected;
6419               pr "               (int) r->%s);\n" field;
6420               pr "      return -1;\n";
6421               pr "    }\n"
6422           | CompareWithString (field, expected) ->
6423               pr "    if (STRNEQ (r->%s, \"%s\")) {\n" field expected;
6424               pr "      fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
6425                 test_name field expected;
6426               pr "               r->%s);\n" field;
6427               pr "      return -1;\n";
6428               pr "    }\n"
6429           | CompareFieldsIntEq (field1, field2) ->
6430               pr "    if (r->%s != r->%s) {\n" field1 field2;
6431               pr "      fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
6432                 test_name field1 field2;
6433               pr "               (int) r->%s, (int) r->%s);\n" field1 field2;
6434               pr "      return -1;\n";
6435               pr "    }\n"
6436           | CompareFieldsStrEq (field1, field2) ->
6437               pr "    if (STRNEQ (r->%s, r->%s)) {\n" field1 field2;
6438               pr "      fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
6439                 test_name field1 field2;
6440               pr "               r->%s, r->%s);\n" field1 field2;
6441               pr "      return -1;\n";
6442               pr "    }\n"
6443         ) checks
6444       in
6445       List.iter (generate_test_command_call test_name) seq;
6446       generate_test_command_call ~test test_name last
6447   | TestLastFail seq ->
6448       pr "  /* TestLastFail for %s (%d) */\n" name i;
6449       let seq, last = get_seq_last seq in
6450       List.iter (generate_test_command_call test_name) seq;
6451       generate_test_command_call test_name ~expect_error:true last
6452
6453 (* Generate the code to run a command, leaving the result in 'r'.
6454  * If you expect to get an error then you should set expect_error:true.
6455  *)
6456 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
6457   match cmd with
6458   | [] -> assert false
6459   | name :: args ->
6460       (* Look up the command to find out what args/ret it has. *)
6461       let style =
6462         try
6463           let _, style, _, _, _, _, _ =
6464             List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
6465           style
6466         with Not_found ->
6467           failwithf "%s: in test, command %s was not found" test_name name in
6468
6469       if List.length (snd style) <> List.length args then
6470         failwithf "%s: in test, wrong number of args given to %s"
6471           test_name name;
6472
6473       pr "  {\n";
6474
6475       List.iter (
6476         function
6477         | OptString n, "NULL" -> ()
6478         | Pathname n, arg
6479         | Device n, arg
6480         | Dev_or_Path n, arg
6481         | String n, arg
6482         | OptString n, arg ->
6483             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
6484         | Int _, _
6485         | Int64 _, _
6486         | Bool _, _
6487         | FileIn _, _ | FileOut _, _ -> ()
6488         | StringList n, arg | DeviceList n, arg ->
6489             let strs = string_split " " arg in
6490             iteri (
6491               fun i str ->
6492                 pr "    const char *%s_%d = \"%s\";\n" n i (c_quote str);
6493             ) strs;
6494             pr "    const char *const %s[] = {\n" n;
6495             iteri (
6496               fun i _ -> pr "      %s_%d,\n" n i
6497             ) strs;
6498             pr "      NULL\n";
6499             pr "    };\n";
6500       ) (List.combine (snd style) args);
6501
6502       let error_code =
6503         match fst style with
6504         | RErr | RInt _ | RBool _ -> pr "    int r;\n"; "-1"
6505         | RInt64 _ -> pr "    int64_t r;\n"; "-1"
6506         | RConstString _ | RConstOptString _ ->
6507             pr "    const char *r;\n"; "NULL"
6508         | RString _ -> pr "    char *r;\n"; "NULL"
6509         | RStringList _ | RHashtable _ ->
6510             pr "    char **r;\n";
6511             pr "    int i;\n";
6512             "NULL"
6513         | RStruct (_, typ) ->
6514             pr "    struct guestfs_%s *r;\n" typ; "NULL"
6515         | RStructList (_, typ) ->
6516             pr "    struct guestfs_%s_list *r;\n" typ; "NULL"
6517         | RBufferOut _ ->
6518             pr "    char *r;\n";
6519             pr "    size_t size;\n";
6520             "NULL" in
6521
6522       pr "    suppress_error = %d;\n" (if expect_error then 1 else 0);
6523       pr "    r = guestfs_%s (g" name;
6524
6525       (* Generate the parameters. *)
6526       List.iter (
6527         function
6528         | OptString _, "NULL" -> pr ", NULL"
6529         | Pathname n, _
6530         | Device n, _ | Dev_or_Path n, _
6531         | String n, _
6532         | OptString n, _ ->
6533             pr ", %s" n
6534         | FileIn _, arg | FileOut _, arg ->
6535             pr ", \"%s\"" (c_quote arg)
6536         | StringList n, _ | DeviceList n, _ ->
6537             pr ", (char **) %s" n
6538         | Int _, arg ->
6539             let i =
6540               try int_of_string arg
6541               with Failure "int_of_string" ->
6542                 failwithf "%s: expecting an int, but got '%s'" test_name arg in
6543             pr ", %d" i
6544         | Int64 _, arg ->
6545             let i =
6546               try Int64.of_string arg
6547               with Failure "int_of_string" ->
6548                 failwithf "%s: expecting an int64, but got '%s'" test_name arg in
6549             pr ", %Ld" i
6550         | Bool _, arg ->
6551             let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
6552       ) (List.combine (snd style) args);
6553
6554       (match fst style with
6555        | RBufferOut _ -> pr ", &size"
6556        | _ -> ()
6557       );
6558
6559       pr ");\n";
6560
6561       if not expect_error then
6562         pr "    if (r == %s)\n" error_code
6563       else
6564         pr "    if (r != %s)\n" error_code;
6565       pr "      return -1;\n";
6566
6567       (* Insert the test code. *)
6568       (match test with
6569        | None -> ()
6570        | Some f -> f ()
6571       );
6572
6573       (match fst style with
6574        | RErr | RInt _ | RInt64 _ | RBool _
6575        | RConstString _ | RConstOptString _ -> ()
6576        | RString _ | RBufferOut _ -> pr "    free (r);\n"
6577        | RStringList _ | RHashtable _ ->
6578            pr "    for (i = 0; r[i] != NULL; ++i)\n";
6579            pr "      free (r[i]);\n";
6580            pr "    free (r);\n"
6581        | RStruct (_, typ) ->
6582            pr "    guestfs_free_%s (r);\n" typ
6583        | RStructList (_, typ) ->
6584            pr "    guestfs_free_%s_list (r);\n" typ
6585       );
6586
6587       pr "  }\n"
6588
6589 and c_quote str =
6590   let str = replace_str str "\r" "\\r" in
6591   let str = replace_str str "\n" "\\n" in
6592   let str = replace_str str "\t" "\\t" in
6593   let str = replace_str str "\000" "\\0" in
6594   str
6595
6596 (* Generate a lot of different functions for guestfish. *)
6597 and generate_fish_cmds () =
6598   generate_header CStyle GPLv2;
6599
6600   let all_functions =
6601     List.filter (
6602       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
6603     ) all_functions in
6604   let all_functions_sorted =
6605     List.filter (
6606       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
6607     ) all_functions_sorted in
6608
6609   pr "#include <stdio.h>\n";
6610   pr "#include <stdlib.h>\n";
6611   pr "#include <string.h>\n";
6612   pr "#include <inttypes.h>\n";
6613   pr "\n";
6614   pr "#include <guestfs.h>\n";
6615   pr "#include \"c-ctype.h\"\n";
6616   pr "#include \"fish.h\"\n";
6617   pr "\n";
6618
6619   (* list_commands function, which implements guestfish -h *)
6620   pr "void list_commands (void)\n";
6621   pr "{\n";
6622   pr "  printf (\"    %%-16s     %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
6623   pr "  list_builtin_commands ();\n";
6624   List.iter (
6625     fun (name, _, _, flags, _, shortdesc, _) ->
6626       let name = replace_char name '_' '-' in
6627       pr "  printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
6628         name shortdesc
6629   ) all_functions_sorted;
6630   pr "  printf (\"    %%s\\n\",";
6631   pr "          _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
6632   pr "}\n";
6633   pr "\n";
6634
6635   (* display_command function, which implements guestfish -h cmd *)
6636   pr "void display_command (const char *cmd)\n";
6637   pr "{\n";
6638   List.iter (
6639     fun (name, style, _, flags, _, shortdesc, longdesc) ->
6640       let name2 = replace_char name '_' '-' in
6641       let alias =
6642         try find_map (function FishAlias n -> Some n | _ -> None) flags
6643         with Not_found -> name in
6644       let longdesc = replace_str longdesc "C<guestfs_" "C<" in
6645       let synopsis =
6646         match snd style with
6647         | [] -> name2
6648         | args ->
6649             sprintf "%s %s"
6650               name2 (String.concat " " (List.map name_of_argt args)) in
6651
6652       let warnings =
6653         if List.mem ProtocolLimitWarning flags then
6654           ("\n\n" ^ protocol_limit_warning)
6655         else "" in
6656
6657       (* For DangerWillRobinson commands, we should probably have
6658        * guestfish prompt before allowing you to use them (especially
6659        * in interactive mode). XXX
6660        *)
6661       let warnings =
6662         warnings ^
6663           if List.mem DangerWillRobinson flags then
6664             ("\n\n" ^ danger_will_robinson)
6665           else "" in
6666
6667       let warnings =
6668         warnings ^
6669           match deprecation_notice flags with
6670           | None -> ""
6671           | Some txt -> "\n\n" ^ txt in
6672
6673       let describe_alias =
6674         if name <> alias then
6675           sprintf "\n\nYou can use '%s' as an alias for this command." alias
6676         else "" in
6677
6678       pr "  if (";
6679       pr "STRCASEEQ (cmd, \"%s\")" name;
6680       if name <> name2 then
6681         pr " || STRCASEEQ (cmd, \"%s\")" name2;
6682       if name <> alias then
6683         pr " || STRCASEEQ (cmd, \"%s\")" alias;
6684       pr ")\n";
6685       pr "    pod2text (\"%s\", _(\"%s\"), %S);\n"
6686         name2 shortdesc
6687         ("=head1 SYNOPSIS\n\n " ^ synopsis ^ "\n\n" ^
6688          "=head1 DESCRIPTION\n\n" ^
6689          longdesc ^ warnings ^ describe_alias);
6690       pr "  else\n"
6691   ) all_functions;
6692   pr "    display_builtin_command (cmd);\n";
6693   pr "}\n";
6694   pr "\n";
6695
6696   let emit_print_list_function typ =
6697     pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
6698       typ typ typ;
6699     pr "{\n";
6700     pr "  unsigned int i;\n";
6701     pr "\n";
6702     pr "  for (i = 0; i < %ss->len; ++i) {\n" typ;
6703     pr "    printf (\"[%%d] = {\\n\", i);\n";
6704     pr "    print_%s_indent (&%ss->val[i], \"  \");\n" typ typ;
6705     pr "    printf (\"}\\n\");\n";
6706     pr "  }\n";
6707     pr "}\n";
6708     pr "\n";
6709   in
6710
6711   (* print_* functions *)
6712   List.iter (
6713     fun (typ, cols) ->
6714       let needs_i =
6715         List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
6716
6717       pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
6718       pr "{\n";
6719       if needs_i then (
6720         pr "  unsigned int i;\n";
6721         pr "\n"
6722       );
6723       List.iter (
6724         function
6725         | name, FString ->
6726             pr "  printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
6727         | name, FUUID ->
6728             pr "  printf (\"%%s%s: \", indent);\n" name;
6729             pr "  for (i = 0; i < 32; ++i)\n";
6730             pr "    printf (\"%%c\", %s->%s[i]);\n" typ name;
6731             pr "  printf (\"\\n\");\n"
6732         | name, FBuffer ->
6733             pr "  printf (\"%%s%s: \", indent);\n" name;
6734             pr "  for (i = 0; i < %s->%s_len; ++i)\n" typ name;
6735             pr "    if (c_isprint (%s->%s[i]))\n" typ name;
6736             pr "      printf (\"%%c\", %s->%s[i]);\n" typ name;
6737             pr "    else\n";
6738             pr "      printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
6739             pr "  printf (\"\\n\");\n"
6740         | name, (FUInt64|FBytes) ->
6741             pr "  printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
6742               name typ name
6743         | name, FInt64 ->
6744             pr "  printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
6745               name typ name
6746         | name, FUInt32 ->
6747             pr "  printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
6748               name typ name
6749         | name, FInt32 ->
6750             pr "  printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
6751               name typ name
6752         | name, FChar ->
6753             pr "  printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
6754               name typ name
6755         | name, FOptPercent ->
6756             pr "  if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
6757               typ name name typ name;
6758             pr "  else printf (\"%%s%s: \\n\", indent);\n" name
6759       ) cols;
6760       pr "}\n";
6761       pr "\n";
6762   ) structs;
6763
6764   (* Emit a print_TYPE_list function definition only if that function is used. *)
6765   List.iter (
6766     function
6767     | typ, (RStructListOnly | RStructAndList) ->
6768         (* generate the function for typ *)
6769         emit_print_list_function typ
6770     | typ, _ -> () (* empty *)
6771   ) (rstructs_used_by all_functions);
6772
6773   (* Emit a print_TYPE function definition only if that function is used. *)
6774   List.iter (
6775     function
6776     | typ, (RStructOnly | RStructAndList) ->
6777         pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
6778         pr "{\n";
6779         pr "  print_%s_indent (%s, \"\");\n" typ typ;
6780         pr "}\n";
6781         pr "\n";
6782     | typ, _ -> () (* empty *)
6783   ) (rstructs_used_by all_functions);
6784
6785   (* run_<action> actions *)
6786   List.iter (
6787     fun (name, style, _, flags, _, _, _) ->
6788       pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
6789       pr "{\n";
6790       (match fst style with
6791        | RErr
6792        | RInt _
6793        | RBool _ -> pr "  int r;\n"
6794        | RInt64 _ -> pr "  int64_t r;\n"
6795        | RConstString _ | RConstOptString _ -> pr "  const char *r;\n"
6796        | RString _ -> pr "  char *r;\n"
6797        | RStringList _ | RHashtable _ -> pr "  char **r;\n"
6798        | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ
6799        | RStructList (_, typ) -> pr "  struct guestfs_%s_list *r;\n" typ
6800        | RBufferOut _ ->
6801            pr "  char *r;\n";
6802            pr "  size_t size;\n";
6803       );
6804       List.iter (
6805         function
6806         | Device n
6807         | String n
6808         | OptString n
6809         | FileIn n
6810         | FileOut n -> pr "  const char *%s;\n" n
6811         | Pathname n
6812         | Dev_or_Path n -> pr "  char *%s;\n" n
6813         | StringList n | DeviceList n -> pr "  char **%s;\n" n
6814         | Bool n -> pr "  int %s;\n" n
6815         | Int n -> pr "  int %s;\n" n
6816         | Int64 n -> pr "  int64_t %s;\n" n
6817       ) (snd style);
6818
6819       (* Check and convert parameters. *)
6820       let argc_expected = List.length (snd style) in
6821       pr "  if (argc != %d) {\n" argc_expected;
6822       pr "    fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
6823         argc_expected;
6824       pr "    fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
6825       pr "    return -1;\n";
6826       pr "  }\n";
6827       iteri (
6828         fun i ->
6829           function
6830           | Device name
6831           | String name ->
6832               pr "  %s = argv[%d];\n" name i
6833           | Pathname name
6834           | Dev_or_Path name ->
6835               pr "  %s = resolve_win_path (argv[%d]);\n" name i;
6836               pr "  if (%s == NULL) return -1;\n" name
6837           | OptString name ->
6838               pr "  %s = STRNEQ (argv[%d], \"\") ? argv[%d] : NULL;\n"
6839                 name i i
6840           | FileIn name ->
6841               pr "  %s = STRNEQ (argv[%d], \"-\") ? argv[%d] : \"/dev/stdin\";\n"
6842                 name i i
6843           | FileOut name ->
6844               pr "  %s = STRNEQ (argv[%d], \"-\") ? argv[%d] : \"/dev/stdout\";\n"
6845                 name i i
6846           | StringList name | DeviceList name ->
6847               pr "  %s = parse_string_list (argv[%d]);\n" name i;
6848               pr "  if (%s == NULL) return -1;\n" name;
6849           | Bool name ->
6850               pr "  %s = is_true (argv[%d]) ? 1 : 0;\n" name i
6851           | Int name ->
6852               pr "  %s = atoi (argv[%d]);\n" name i
6853           | Int64 name ->
6854               pr "  %s = atoll (argv[%d]);\n" name i
6855       ) (snd style);
6856
6857       (* Call C API function. *)
6858       let fn =
6859         try find_map (function FishAction n -> Some n | _ -> None) flags
6860         with Not_found -> sprintf "guestfs_%s" name in
6861       pr "  r = %s " fn;
6862       generate_c_call_args ~handle:"g" style;
6863       pr ";\n";
6864
6865       List.iter (
6866         function
6867         | Device name | String name
6868         | OptString name | FileIn name | FileOut name | Bool name
6869         | Int name | Int64 name -> ()
6870         | Pathname name | Dev_or_Path name ->
6871             pr "  free (%s);\n" name
6872         | StringList name | DeviceList name ->
6873             pr "  free_strings (%s);\n" name
6874       ) (snd style);
6875
6876       (* Check return value for errors and display command results. *)
6877       (match fst style with
6878        | RErr -> pr "  return r;\n"
6879        | RInt _ ->
6880            pr "  if (r == -1) return -1;\n";
6881            pr "  printf (\"%%d\\n\", r);\n";
6882            pr "  return 0;\n"
6883        | RInt64 _ ->
6884            pr "  if (r == -1) return -1;\n";
6885            pr "  printf (\"%%\" PRIi64 \"\\n\", r);\n";
6886            pr "  return 0;\n"
6887        | RBool _ ->
6888            pr "  if (r == -1) return -1;\n";
6889            pr "  if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
6890            pr "  return 0;\n"
6891        | RConstString _ ->
6892            pr "  if (r == NULL) return -1;\n";
6893            pr "  printf (\"%%s\\n\", r);\n";
6894            pr "  return 0;\n"
6895        | RConstOptString _ ->
6896            pr "  printf (\"%%s\\n\", r ? : \"(null)\");\n";
6897            pr "  return 0;\n"
6898        | RString _ ->
6899            pr "  if (r == NULL) return -1;\n";
6900            pr "  printf (\"%%s\\n\", r);\n";
6901            pr "  free (r);\n";
6902            pr "  return 0;\n"
6903        | RStringList _ ->
6904            pr "  if (r == NULL) return -1;\n";
6905            pr "  print_strings (r);\n";
6906            pr "  free_strings (r);\n";
6907            pr "  return 0;\n"
6908        | RStruct (_, typ) ->
6909            pr "  if (r == NULL) return -1;\n";
6910            pr "  print_%s (r);\n" typ;
6911            pr "  guestfs_free_%s (r);\n" typ;
6912            pr "  return 0;\n"
6913        | RStructList (_, typ) ->
6914            pr "  if (r == NULL) return -1;\n";
6915            pr "  print_%s_list (r);\n" typ;
6916            pr "  guestfs_free_%s_list (r);\n" typ;
6917            pr "  return 0;\n"
6918        | RHashtable _ ->
6919            pr "  if (r == NULL) return -1;\n";
6920            pr "  print_table (r);\n";
6921            pr "  free_strings (r);\n";
6922            pr "  return 0;\n"
6923        | RBufferOut _ ->
6924            pr "  if (r == NULL) return -1;\n";
6925            pr "  fwrite (r, size, 1, stdout);\n";
6926            pr "  free (r);\n";
6927            pr "  return 0;\n"
6928       );
6929       pr "}\n";
6930       pr "\n"
6931   ) all_functions;
6932
6933   (* run_action function *)
6934   pr "int run_action (const char *cmd, int argc, char *argv[])\n";
6935   pr "{\n";
6936   List.iter (
6937     fun (name, _, _, flags, _, _, _) ->
6938       let name2 = replace_char name '_' '-' in
6939       let alias =
6940         try find_map (function FishAlias n -> Some n | _ -> None) flags
6941         with Not_found -> name in
6942       pr "  if (";
6943       pr "STRCASEEQ (cmd, \"%s\")" name;
6944       if name <> name2 then
6945         pr " || STRCASEEQ (cmd, \"%s\")" name2;
6946       if name <> alias then
6947         pr " || STRCASEEQ (cmd, \"%s\")" alias;
6948       pr ")\n";
6949       pr "    return run_%s (cmd, argc, argv);\n" name;
6950       pr "  else\n";
6951   ) all_functions;
6952   pr "    {\n";
6953   pr "      fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
6954   pr "      return -1;\n";
6955   pr "    }\n";
6956   pr "  return 0;\n";
6957   pr "}\n";
6958   pr "\n"
6959
6960 (* Readline completion for guestfish. *)
6961 and generate_fish_completion () =
6962   generate_header CStyle GPLv2;
6963
6964   let all_functions =
6965     List.filter (
6966       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
6967     ) all_functions in
6968
6969   pr "\
6970 #include <config.h>
6971
6972 #include <stdio.h>
6973 #include <stdlib.h>
6974 #include <string.h>
6975
6976 #ifdef HAVE_LIBREADLINE
6977 #include <readline/readline.h>
6978 #endif
6979
6980 #include \"fish.h\"
6981
6982 #ifdef HAVE_LIBREADLINE
6983
6984 static const char *const commands[] = {
6985   BUILTIN_COMMANDS_FOR_COMPLETION,
6986 ";
6987
6988   (* Get the commands, including the aliases.  They don't need to be
6989    * sorted - the generator() function just does a dumb linear search.
6990    *)
6991   let commands =
6992     List.map (
6993       fun (name, _, _, flags, _, _, _) ->
6994         let name2 = replace_char name '_' '-' in
6995         let alias =
6996           try find_map (function FishAlias n -> Some n | _ -> None) flags
6997           with Not_found -> name in
6998
6999         if name <> alias then [name2; alias] else [name2]
7000     ) all_functions in
7001   let commands = List.flatten commands in
7002
7003   List.iter (pr "  \"%s\",\n") commands;
7004
7005   pr "  NULL
7006 };
7007
7008 static char *
7009 generator (const char *text, int state)
7010 {
7011   static int index, len;
7012   const char *name;
7013
7014   if (!state) {
7015     index = 0;
7016     len = strlen (text);
7017   }
7018
7019   rl_attempted_completion_over = 1;
7020
7021   while ((name = commands[index]) != NULL) {
7022     index++;
7023     if (STRCASEEQLEN (name, text, len))
7024       return strdup (name);
7025   }
7026
7027   return NULL;
7028 }
7029
7030 #endif /* HAVE_LIBREADLINE */
7031
7032 char **do_completion (const char *text, int start, int end)
7033 {
7034   char **matches = NULL;
7035
7036 #ifdef HAVE_LIBREADLINE
7037   rl_completion_append_character = ' ';
7038
7039   if (start == 0)
7040     matches = rl_completion_matches (text, generator);
7041   else if (complete_dest_paths)
7042     matches = rl_completion_matches (text, complete_dest_paths_generator);
7043 #endif
7044
7045   return matches;
7046 }
7047 ";
7048
7049 (* Generate the POD documentation for guestfish. *)
7050 and generate_fish_actions_pod () =
7051   let all_functions_sorted =
7052     List.filter (
7053       fun (_, _, _, flags, _, _, _) ->
7054         not (List.mem NotInFish flags || List.mem NotInDocs flags)
7055     ) all_functions_sorted in
7056
7057   let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
7058
7059   List.iter (
7060     fun (name, style, _, flags, _, _, longdesc) ->
7061       let longdesc =
7062         Str.global_substitute rex (
7063           fun s ->
7064             let sub =
7065               try Str.matched_group 1 s
7066               with Not_found ->
7067                 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
7068             "C<" ^ replace_char sub '_' '-' ^ ">"
7069         ) longdesc in
7070       let name = replace_char name '_' '-' in
7071       let alias =
7072         try find_map (function FishAlias n -> Some n | _ -> None) flags
7073         with Not_found -> name in
7074
7075       pr "=head2 %s" name;
7076       if name <> alias then
7077         pr " | %s" alias;
7078       pr "\n";
7079       pr "\n";
7080       pr " %s" name;
7081       List.iter (
7082         function
7083         | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
7084         | OptString n -> pr " %s" n
7085         | StringList n | DeviceList n -> pr " '%s ...'" n
7086         | Bool _ -> pr " true|false"
7087         | Int n -> pr " %s" n
7088         | Int64 n -> pr " %s" n
7089         | FileIn n | FileOut n -> pr " (%s|-)" n
7090       ) (snd style);
7091       pr "\n";
7092       pr "\n";
7093       pr "%s\n\n" longdesc;
7094
7095       if List.exists (function FileIn _ | FileOut _ -> true
7096                       | _ -> false) (snd style) then
7097         pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
7098
7099       if List.mem ProtocolLimitWarning flags then
7100         pr "%s\n\n" protocol_limit_warning;
7101
7102       if List.mem DangerWillRobinson flags then
7103         pr "%s\n\n" danger_will_robinson;
7104
7105       match deprecation_notice flags with
7106       | None -> ()
7107       | Some txt -> pr "%s\n\n" txt
7108   ) all_functions_sorted
7109
7110 (* Generate a C function prototype. *)
7111 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
7112     ?(single_line = false) ?(newline = false) ?(in_daemon = false)
7113     ?(prefix = "")
7114     ?handle name style =
7115   if extern then pr "extern ";
7116   if static then pr "static ";
7117   (match fst style with
7118    | RErr -> pr "int "
7119    | RInt _ -> pr "int "
7120    | RInt64 _ -> pr "int64_t "
7121    | RBool _ -> pr "int "
7122    | RConstString _ | RConstOptString _ -> pr "const char *"
7123    | RString _ | RBufferOut _ -> pr "char *"
7124    | RStringList _ | RHashtable _ -> pr "char **"
7125    | RStruct (_, typ) ->
7126        if not in_daemon then pr "struct guestfs_%s *" typ
7127        else pr "guestfs_int_%s *" typ
7128    | RStructList (_, typ) ->
7129        if not in_daemon then pr "struct guestfs_%s_list *" typ
7130        else pr "guestfs_int_%s_list *" typ
7131   );
7132   let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
7133   pr "%s%s (" prefix name;
7134   if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
7135     pr "void"
7136   else (
7137     let comma = ref false in
7138     (match handle with
7139      | None -> ()
7140      | Some handle -> pr "guestfs_h *%s" handle; comma := true
7141     );
7142     let next () =
7143       if !comma then (
7144         if single_line then pr ", " else pr ",\n\t\t"
7145       );
7146       comma := true
7147     in
7148     List.iter (
7149       function
7150       | Pathname n
7151       | Device n | Dev_or_Path n
7152       | String n
7153       | OptString n ->
7154           next ();
7155           pr "const char *%s" n
7156       | StringList n | DeviceList n ->
7157           next ();
7158           pr "char *const *%s" n
7159       | Bool n -> next (); pr "int %s" n
7160       | Int n -> next (); pr "int %s" n
7161       | Int64 n -> next (); pr "int64_t %s" n
7162       | FileIn n
7163       | FileOut n ->
7164           if not in_daemon then (next (); pr "const char *%s" n)
7165     ) (snd style);
7166     if is_RBufferOut then (next (); pr "size_t *size_r");
7167   );
7168   pr ")";
7169   if semicolon then pr ";";
7170   if newline then pr "\n"
7171
7172 (* Generate C call arguments, eg "(handle, foo, bar)" *)
7173 and generate_c_call_args ?handle ?(decl = false) style =
7174   pr "(";
7175   let comma = ref false in
7176   let next () =
7177     if !comma then pr ", ";
7178     comma := true
7179   in
7180   (match handle with
7181    | None -> ()
7182    | Some handle -> pr "%s" handle; comma := true
7183   );
7184   List.iter (
7185     fun arg ->
7186       next ();
7187       pr "%s" (name_of_argt arg)
7188   ) (snd style);
7189   (* For RBufferOut calls, add implicit &size parameter. *)
7190   if not decl then (
7191     match fst style with
7192     | RBufferOut _ ->
7193         next ();
7194         pr "&size"
7195     | _ -> ()
7196   );
7197   pr ")"
7198
7199 (* Generate the OCaml bindings interface. *)
7200 and generate_ocaml_mli () =
7201   generate_header OCamlStyle LGPLv2;
7202
7203   pr "\
7204 (** For API documentation you should refer to the C API
7205     in the guestfs(3) manual page.  The OCaml API uses almost
7206     exactly the same calls. *)
7207
7208 type t
7209 (** A [guestfs_h] handle. *)
7210
7211 exception Error of string
7212 (** This exception is raised when there is an error. *)
7213
7214 exception Handle_closed of string
7215 (** This exception is raised if you use a {!Guestfs.t} handle
7216     after calling {!close} on it.  The string is the name of
7217     the function. *)
7218
7219 val create : unit -> t
7220 (** Create a {!Guestfs.t} handle. *)
7221
7222 val close : t -> unit
7223 (** Close the {!Guestfs.t} handle and free up all resources used
7224     by it immediately.
7225
7226     Handles are closed by the garbage collector when they become
7227     unreferenced, but callers can call this in order to provide
7228     predictable cleanup. *)
7229
7230 ";
7231   generate_ocaml_structure_decls ();
7232
7233   (* The actions. *)
7234   List.iter (
7235     fun (name, style, _, _, _, shortdesc, _) ->
7236       generate_ocaml_prototype name style;
7237       pr "(** %s *)\n" shortdesc;
7238       pr "\n"
7239   ) all_functions_sorted
7240
7241 (* Generate the OCaml bindings implementation. *)
7242 and generate_ocaml_ml () =
7243   generate_header OCamlStyle LGPLv2;
7244
7245   pr "\
7246 type t
7247
7248 exception Error of string
7249 exception Handle_closed of string
7250
7251 external create : unit -> t = \"ocaml_guestfs_create\"
7252 external close : t -> unit = \"ocaml_guestfs_close\"
7253
7254 (* Give the exceptions names, so they can be raised from the C code. *)
7255 let () =
7256   Callback.register_exception \"ocaml_guestfs_error\" (Error \"\");
7257   Callback.register_exception \"ocaml_guestfs_closed\" (Handle_closed \"\")
7258
7259 ";
7260
7261   generate_ocaml_structure_decls ();
7262
7263   (* The actions. *)
7264   List.iter (
7265     fun (name, style, _, _, _, shortdesc, _) ->
7266       generate_ocaml_prototype ~is_external:true name style;
7267   ) all_functions_sorted
7268
7269 (* Generate the OCaml bindings C implementation. *)
7270 and generate_ocaml_c () =
7271   generate_header CStyle LGPLv2;
7272
7273   pr "\
7274 #include <stdio.h>
7275 #include <stdlib.h>
7276 #include <string.h>
7277
7278 #include <caml/config.h>
7279 #include <caml/alloc.h>
7280 #include <caml/callback.h>
7281 #include <caml/fail.h>
7282 #include <caml/memory.h>
7283 #include <caml/mlvalues.h>
7284 #include <caml/signals.h>
7285
7286 #include <guestfs.h>
7287
7288 #include \"guestfs_c.h\"
7289
7290 /* Copy a hashtable of string pairs into an assoc-list.  We return
7291  * the list in reverse order, but hashtables aren't supposed to be
7292  * ordered anyway.
7293  */
7294 static CAMLprim value
7295 copy_table (char * const * argv)
7296 {
7297   CAMLparam0 ();
7298   CAMLlocal5 (rv, pairv, kv, vv, cons);
7299   int i;
7300
7301   rv = Val_int (0);
7302   for (i = 0; argv[i] != NULL; i += 2) {
7303     kv = caml_copy_string (argv[i]);
7304     vv = caml_copy_string (argv[i+1]);
7305     pairv = caml_alloc (2, 0);
7306     Store_field (pairv, 0, kv);
7307     Store_field (pairv, 1, vv);
7308     cons = caml_alloc (2, 0);
7309     Store_field (cons, 1, rv);
7310     rv = cons;
7311     Store_field (cons, 0, pairv);
7312   }
7313
7314   CAMLreturn (rv);
7315 }
7316
7317 ";
7318
7319   (* Struct copy functions. *)
7320
7321   let emit_ocaml_copy_list_function typ =
7322     pr "static CAMLprim value\n";
7323     pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
7324     pr "{\n";
7325     pr "  CAMLparam0 ();\n";
7326     pr "  CAMLlocal2 (rv, v);\n";
7327     pr "  unsigned int i;\n";
7328     pr "\n";
7329     pr "  if (%ss->len == 0)\n" typ;
7330     pr "    CAMLreturn (Atom (0));\n";
7331     pr "  else {\n";
7332     pr "    rv = caml_alloc (%ss->len, 0);\n" typ;
7333     pr "    for (i = 0; i < %ss->len; ++i) {\n" typ;
7334     pr "      v = copy_%s (&%ss->val[i]);\n" typ typ;
7335     pr "      caml_modify (&Field (rv, i), v);\n";
7336     pr "    }\n";
7337     pr "    CAMLreturn (rv);\n";
7338     pr "  }\n";
7339     pr "}\n";
7340     pr "\n";
7341   in
7342
7343   List.iter (
7344     fun (typ, cols) ->
7345       let has_optpercent_col =
7346         List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
7347
7348       pr "static CAMLprim value\n";
7349       pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
7350       pr "{\n";
7351       pr "  CAMLparam0 ();\n";
7352       if has_optpercent_col then
7353         pr "  CAMLlocal3 (rv, v, v2);\n"
7354       else
7355         pr "  CAMLlocal2 (rv, v);\n";
7356       pr "\n";
7357       pr "  rv = caml_alloc (%d, 0);\n" (List.length cols);
7358       iteri (
7359         fun i col ->
7360           (match col with
7361            | name, FString ->
7362                pr "  v = caml_copy_string (%s->%s);\n" typ name
7363            | name, FBuffer ->
7364                pr "  v = caml_alloc_string (%s->%s_len);\n" typ name;
7365                pr "  memcpy (String_val (v), %s->%s, %s->%s_len);\n"
7366                  typ name typ name
7367            | name, FUUID ->
7368                pr "  v = caml_alloc_string (32);\n";
7369                pr "  memcpy (String_val (v), %s->%s, 32);\n" typ name
7370            | name, (FBytes|FInt64|FUInt64) ->
7371                pr "  v = caml_copy_int64 (%s->%s);\n" typ name
7372            | name, (FInt32|FUInt32) ->
7373                pr "  v = caml_copy_int32 (%s->%s);\n" typ name
7374            | name, FOptPercent ->
7375                pr "  if (%s->%s >= 0) { /* Some %s */\n" typ name name;
7376                pr "    v2 = caml_copy_double (%s->%s);\n" typ name;
7377                pr "    v = caml_alloc (1, 0);\n";
7378                pr "    Store_field (v, 0, v2);\n";
7379                pr "  } else /* None */\n";
7380                pr "    v = Val_int (0);\n";
7381            | name, FChar ->
7382                pr "  v = Val_int (%s->%s);\n" typ name
7383           );
7384           pr "  Store_field (rv, %d, v);\n" i
7385       ) cols;
7386       pr "  CAMLreturn (rv);\n";
7387       pr "}\n";
7388       pr "\n";
7389   ) structs;
7390
7391   (* Emit a copy_TYPE_list function definition only if that function is used. *)
7392   List.iter (
7393     function
7394     | typ, (RStructListOnly | RStructAndList) ->
7395         (* generate the function for typ *)
7396         emit_ocaml_copy_list_function typ
7397     | typ, _ -> () (* empty *)
7398   ) (rstructs_used_by all_functions);
7399
7400   (* The wrappers. *)
7401   List.iter (
7402     fun (name, style, _, _, _, _, _) ->
7403       pr "/* Automatically generated wrapper for function\n";
7404       pr " * ";
7405       generate_ocaml_prototype name style;
7406       pr " */\n";
7407       pr "\n";
7408
7409       let params =
7410         "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
7411
7412       let needs_extra_vs =
7413         match fst style with RConstOptString _ -> true | _ -> false in
7414
7415       pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
7416       pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
7417       List.iter (pr ", value %s") (List.tl params); pr ");\n";
7418       pr "\n";
7419
7420       pr "CAMLprim value\n";
7421       pr "ocaml_guestfs_%s (value %s" name (List.hd params);
7422       List.iter (pr ", value %s") (List.tl params);
7423       pr ")\n";
7424       pr "{\n";
7425
7426       (match params with
7427        | [p1; p2; p3; p4; p5] ->
7428            pr "  CAMLparam5 (%s);\n" (String.concat ", " params)
7429        | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
7430            pr "  CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
7431            pr "  CAMLxparam%d (%s);\n"
7432              (List.length rest) (String.concat ", " rest)
7433        | ps ->
7434            pr "  CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
7435       );
7436       if not needs_extra_vs then
7437         pr "  CAMLlocal1 (rv);\n"
7438       else
7439         pr "  CAMLlocal3 (rv, v, v2);\n";
7440       pr "\n";
7441
7442       pr "  guestfs_h *g = Guestfs_val (gv);\n";
7443       pr "  if (g == NULL)\n";
7444       pr "    ocaml_guestfs_raise_closed (\"%s\");\n" name;
7445       pr "\n";
7446
7447       List.iter (
7448         function
7449         | Pathname n
7450         | Device n | Dev_or_Path n
7451         | String n
7452         | FileIn n
7453         | FileOut n ->
7454             pr "  const char *%s = String_val (%sv);\n" n n
7455         | OptString n ->
7456             pr "  const char *%s =\n" n;
7457             pr "    %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
7458               n n
7459         | StringList n | DeviceList n ->
7460             pr "  char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
7461         | Bool n ->
7462             pr "  int %s = Bool_val (%sv);\n" n n
7463         | Int n ->
7464             pr "  int %s = Int_val (%sv);\n" n n
7465         | Int64 n ->
7466             pr "  int64_t %s = Int64_val (%sv);\n" n n
7467       ) (snd style);
7468       let error_code =
7469         match fst style with
7470         | RErr -> pr "  int r;\n"; "-1"
7471         | RInt _ -> pr "  int r;\n"; "-1"
7472         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
7473         | RBool _ -> pr "  int r;\n"; "-1"
7474         | RConstString _ | RConstOptString _ ->
7475             pr "  const char *r;\n"; "NULL"
7476         | RString _ -> pr "  char *r;\n"; "NULL"
7477         | RStringList _ ->
7478             pr "  int i;\n";
7479             pr "  char **r;\n";
7480             "NULL"
7481         | RStruct (_, typ) ->
7482             pr "  struct guestfs_%s *r;\n" typ; "NULL"
7483         | RStructList (_, typ) ->
7484             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
7485         | RHashtable _ ->
7486             pr "  int i;\n";
7487             pr "  char **r;\n";
7488             "NULL"
7489         | RBufferOut _ ->
7490             pr "  char *r;\n";
7491             pr "  size_t size;\n";
7492             "NULL" in
7493       pr "\n";
7494
7495       pr "  caml_enter_blocking_section ();\n";
7496       pr "  r = guestfs_%s " name;
7497       generate_c_call_args ~handle:"g" style;
7498       pr ";\n";
7499       pr "  caml_leave_blocking_section ();\n";
7500
7501       List.iter (
7502         function
7503         | StringList n | DeviceList n ->
7504             pr "  ocaml_guestfs_free_strings (%s);\n" n;
7505         | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
7506         | Bool _ | Int _ | Int64 _
7507         | FileIn _ | FileOut _ -> ()
7508       ) (snd style);
7509
7510       pr "  if (r == %s)\n" error_code;
7511       pr "    ocaml_guestfs_raise_error (g, \"%s\");\n" name;
7512       pr "\n";
7513
7514       (match fst style with
7515        | RErr -> pr "  rv = Val_unit;\n"
7516        | RInt _ -> pr "  rv = Val_int (r);\n"
7517        | RInt64 _ ->
7518            pr "  rv = caml_copy_int64 (r);\n"
7519        | RBool _ -> pr "  rv = Val_bool (r);\n"
7520        | RConstString _ ->
7521            pr "  rv = caml_copy_string (r);\n"
7522        | RConstOptString _ ->
7523            pr "  if (r) { /* Some string */\n";
7524            pr "    v = caml_alloc (1, 0);\n";
7525            pr "    v2 = caml_copy_string (r);\n";
7526            pr "    Store_field (v, 0, v2);\n";
7527            pr "  } else /* None */\n";
7528            pr "    v = Val_int (0);\n";
7529        | RString _ ->
7530            pr "  rv = caml_copy_string (r);\n";
7531            pr "  free (r);\n"
7532        | RStringList _ ->
7533            pr "  rv = caml_copy_string_array ((const char **) r);\n";
7534            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
7535            pr "  free (r);\n"
7536        | RStruct (_, typ) ->
7537            pr "  rv = copy_%s (r);\n" typ;
7538            pr "  guestfs_free_%s (r);\n" typ;
7539        | RStructList (_, typ) ->
7540            pr "  rv = copy_%s_list (r);\n" typ;
7541            pr "  guestfs_free_%s_list (r);\n" typ;
7542        | RHashtable _ ->
7543            pr "  rv = copy_table (r);\n";
7544            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
7545            pr "  free (r);\n";
7546        | RBufferOut _ ->
7547            pr "  rv = caml_alloc_string (size);\n";
7548            pr "  memcpy (String_val (rv), r, size);\n";
7549       );
7550
7551       pr "  CAMLreturn (rv);\n";
7552       pr "}\n";
7553       pr "\n";
7554
7555       if List.length params > 5 then (
7556         pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
7557         pr "CAMLprim value ";
7558         pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
7559         pr "CAMLprim value\n";
7560         pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
7561         pr "{\n";
7562         pr "  return ocaml_guestfs_%s (argv[0]" name;
7563         iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
7564         pr ");\n";
7565         pr "}\n";
7566         pr "\n"
7567       )
7568   ) all_functions_sorted
7569
7570 and generate_ocaml_structure_decls () =
7571   List.iter (
7572     fun (typ, cols) ->
7573       pr "type %s = {\n" typ;
7574       List.iter (
7575         function
7576         | name, FString -> pr "  %s : string;\n" name
7577         | name, FBuffer -> pr "  %s : string;\n" name
7578         | name, FUUID -> pr "  %s : string;\n" name
7579         | name, (FBytes|FInt64|FUInt64) -> pr "  %s : int64;\n" name
7580         | name, (FInt32|FUInt32) -> pr "  %s : int32;\n" name
7581         | name, FChar -> pr "  %s : char;\n" name
7582         | name, FOptPercent -> pr "  %s : float option;\n" name
7583       ) cols;
7584       pr "}\n";
7585       pr "\n"
7586   ) structs
7587
7588 and generate_ocaml_prototype ?(is_external = false) name style =
7589   if is_external then pr "external " else pr "val ";
7590   pr "%s : t -> " name;
7591   List.iter (
7592     function
7593     | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "string -> "
7594     | OptString _ -> pr "string option -> "
7595     | StringList _ | DeviceList _ -> pr "string array -> "
7596     | Bool _ -> pr "bool -> "
7597     | Int _ -> pr "int -> "
7598     | Int64 _ -> pr "int64 -> "
7599   ) (snd style);
7600   (match fst style with
7601    | RErr -> pr "unit" (* all errors are turned into exceptions *)
7602    | RInt _ -> pr "int"
7603    | RInt64 _ -> pr "int64"
7604    | RBool _ -> pr "bool"
7605    | RConstString _ -> pr "string"
7606    | RConstOptString _ -> pr "string option"
7607    | RString _ | RBufferOut _ -> pr "string"
7608    | RStringList _ -> pr "string array"
7609    | RStruct (_, typ) -> pr "%s" typ
7610    | RStructList (_, typ) -> pr "%s array" typ
7611    | RHashtable _ -> pr "(string * string) list"
7612   );
7613   if is_external then (
7614     pr " = ";
7615     if List.length (snd style) + 1 > 5 then
7616       pr "\"ocaml_guestfs_%s_byte\" " name;
7617     pr "\"ocaml_guestfs_%s\"" name
7618   );
7619   pr "\n"
7620
7621 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
7622 and generate_perl_xs () =
7623   generate_header CStyle LGPLv2;
7624
7625   pr "\
7626 #include \"EXTERN.h\"
7627 #include \"perl.h\"
7628 #include \"XSUB.h\"
7629
7630 #include <guestfs.h>
7631
7632 #ifndef PRId64
7633 #define PRId64 \"lld\"
7634 #endif
7635
7636 static SV *
7637 my_newSVll(long long val) {
7638 #ifdef USE_64_BIT_ALL
7639   return newSViv(val);
7640 #else
7641   char buf[100];
7642   int len;
7643   len = snprintf(buf, 100, \"%%\" PRId64, val);
7644   return newSVpv(buf, len);
7645 #endif
7646 }
7647
7648 #ifndef PRIu64
7649 #define PRIu64 \"llu\"
7650 #endif
7651
7652 static SV *
7653 my_newSVull(unsigned long long val) {
7654 #ifdef USE_64_BIT_ALL
7655   return newSVuv(val);
7656 #else
7657   char buf[100];
7658   int len;
7659   len = snprintf(buf, 100, \"%%\" PRIu64, val);
7660   return newSVpv(buf, len);
7661 #endif
7662 }
7663
7664 /* http://www.perlmonks.org/?node_id=680842 */
7665 static char **
7666 XS_unpack_charPtrPtr (SV *arg) {
7667   char **ret;
7668   AV *av;
7669   I32 i;
7670
7671   if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
7672     croak (\"array reference expected\");
7673
7674   av = (AV *)SvRV (arg);
7675   ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
7676   if (!ret)
7677     croak (\"malloc failed\");
7678
7679   for (i = 0; i <= av_len (av); i++) {
7680     SV **elem = av_fetch (av, i, 0);
7681
7682     if (!elem || !*elem)
7683       croak (\"missing element in list\");
7684
7685     ret[i] = SvPV_nolen (*elem);
7686   }
7687
7688   ret[i] = NULL;
7689
7690   return ret;
7691 }
7692
7693 MODULE = Sys::Guestfs  PACKAGE = Sys::Guestfs
7694
7695 PROTOTYPES: ENABLE
7696
7697 guestfs_h *
7698 _create ()
7699    CODE:
7700       RETVAL = guestfs_create ();
7701       if (!RETVAL)
7702         croak (\"could not create guestfs handle\");
7703       guestfs_set_error_handler (RETVAL, NULL, NULL);
7704  OUTPUT:
7705       RETVAL
7706
7707 void
7708 DESTROY (g)
7709       guestfs_h *g;
7710  PPCODE:
7711       guestfs_close (g);
7712
7713 ";
7714
7715   List.iter (
7716     fun (name, style, _, _, _, _, _) ->
7717       (match fst style with
7718        | RErr -> pr "void\n"
7719        | RInt _ -> pr "SV *\n"
7720        | RInt64 _ -> pr "SV *\n"
7721        | RBool _ -> pr "SV *\n"
7722        | RConstString _ -> pr "SV *\n"
7723        | RConstOptString _ -> pr "SV *\n"
7724        | RString _ -> pr "SV *\n"
7725        | RBufferOut _ -> pr "SV *\n"
7726        | RStringList _
7727        | RStruct _ | RStructList _
7728        | RHashtable _ ->
7729            pr "void\n" (* all lists returned implictly on the stack *)
7730       );
7731       (* Call and arguments. *)
7732       pr "%s " name;
7733       generate_c_call_args ~handle:"g" ~decl:true style;
7734       pr "\n";
7735       pr "      guestfs_h *g;\n";
7736       iteri (
7737         fun i ->
7738           function
7739           | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
7740               pr "      char *%s;\n" n
7741           | OptString n ->
7742               (* http://www.perlmonks.org/?node_id=554277
7743                * Note that the implicit handle argument means we have
7744                * to add 1 to the ST(x) operator.
7745                *)
7746               pr "      char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
7747           | StringList n | DeviceList n -> pr "      char **%s;\n" n
7748           | Bool n -> pr "      int %s;\n" n
7749           | Int n -> pr "      int %s;\n" n
7750           | Int64 n -> pr "      int64_t %s;\n" n
7751       ) (snd style);
7752
7753       let do_cleanups () =
7754         List.iter (
7755           function
7756           | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
7757           | Bool _ | Int _ | Int64 _
7758           | FileIn _ | FileOut _ -> ()
7759           | StringList n | DeviceList n -> pr "      free (%s);\n" n
7760         ) (snd style)
7761       in
7762
7763       (* Code. *)
7764       (match fst style with
7765        | RErr ->
7766            pr "PREINIT:\n";
7767            pr "      int r;\n";
7768            pr " PPCODE:\n";
7769            pr "      r = guestfs_%s " name;
7770            generate_c_call_args ~handle:"g" style;
7771            pr ";\n";
7772            do_cleanups ();
7773            pr "      if (r == -1)\n";
7774            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7775        | RInt n
7776        | RBool n ->
7777            pr "PREINIT:\n";
7778            pr "      int %s;\n" n;
7779            pr "   CODE:\n";
7780            pr "      %s = guestfs_%s " n name;
7781            generate_c_call_args ~handle:"g" style;
7782            pr ";\n";
7783            do_cleanups ();
7784            pr "      if (%s == -1)\n" n;
7785            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7786            pr "      RETVAL = newSViv (%s);\n" n;
7787            pr " OUTPUT:\n";
7788            pr "      RETVAL\n"
7789        | RInt64 n ->
7790            pr "PREINIT:\n";
7791            pr "      int64_t %s;\n" n;
7792            pr "   CODE:\n";
7793            pr "      %s = guestfs_%s " n name;
7794            generate_c_call_args ~handle:"g" style;
7795            pr ";\n";
7796            do_cleanups ();
7797            pr "      if (%s == -1)\n" n;
7798            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7799            pr "      RETVAL = my_newSVll (%s);\n" n;
7800            pr " OUTPUT:\n";
7801            pr "      RETVAL\n"
7802        | RConstString n ->
7803            pr "PREINIT:\n";
7804            pr "      const char *%s;\n" n;
7805            pr "   CODE:\n";
7806            pr "      %s = guestfs_%s " n name;
7807            generate_c_call_args ~handle:"g" style;
7808            pr ";\n";
7809            do_cleanups ();
7810            pr "      if (%s == NULL)\n" n;
7811            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7812            pr "      RETVAL = newSVpv (%s, 0);\n" n;
7813            pr " OUTPUT:\n";
7814            pr "      RETVAL\n"
7815        | RConstOptString n ->
7816            pr "PREINIT:\n";
7817            pr "      const char *%s;\n" n;
7818            pr "   CODE:\n";
7819            pr "      %s = guestfs_%s " n name;
7820            generate_c_call_args ~handle:"g" style;
7821            pr ";\n";
7822            do_cleanups ();
7823            pr "      if (%s == NULL)\n" n;
7824            pr "        RETVAL = &PL_sv_undef;\n";
7825            pr "      else\n";
7826            pr "        RETVAL = newSVpv (%s, 0);\n" n;
7827            pr " OUTPUT:\n";
7828            pr "      RETVAL\n"
7829        | RString n ->
7830            pr "PREINIT:\n";
7831            pr "      char *%s;\n" n;
7832            pr "   CODE:\n";
7833            pr "      %s = guestfs_%s " n name;
7834            generate_c_call_args ~handle:"g" style;
7835            pr ";\n";
7836            do_cleanups ();
7837            pr "      if (%s == NULL)\n" n;
7838            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7839            pr "      RETVAL = newSVpv (%s, 0);\n" n;
7840            pr "      free (%s);\n" n;
7841            pr " OUTPUT:\n";
7842            pr "      RETVAL\n"
7843        | RStringList n | RHashtable n ->
7844            pr "PREINIT:\n";
7845            pr "      char **%s;\n" n;
7846            pr "      int i, n;\n";
7847            pr " PPCODE:\n";
7848            pr "      %s = guestfs_%s " n name;
7849            generate_c_call_args ~handle:"g" style;
7850            pr ";\n";
7851            do_cleanups ();
7852            pr "      if (%s == NULL)\n" n;
7853            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7854            pr "      for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
7855            pr "      EXTEND (SP, n);\n";
7856            pr "      for (i = 0; i < n; ++i) {\n";
7857            pr "        PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
7858            pr "        free (%s[i]);\n" n;
7859            pr "      }\n";
7860            pr "      free (%s);\n" n;
7861        | RStruct (n, typ) ->
7862            let cols = cols_of_struct typ in
7863            generate_perl_struct_code typ cols name style n do_cleanups
7864        | RStructList (n, typ) ->
7865            let cols = cols_of_struct typ in
7866            generate_perl_struct_list_code typ cols name style n do_cleanups
7867        | RBufferOut n ->
7868            pr "PREINIT:\n";
7869            pr "      char *%s;\n" n;
7870            pr "      size_t size;\n";
7871            pr "   CODE:\n";
7872            pr "      %s = guestfs_%s " n name;
7873            generate_c_call_args ~handle:"g" style;
7874            pr ";\n";
7875            do_cleanups ();
7876            pr "      if (%s == NULL)\n" n;
7877            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7878            pr "      RETVAL = newSVpv (%s, size);\n" n;
7879            pr "      free (%s);\n" n;
7880            pr " OUTPUT:\n";
7881            pr "      RETVAL\n"
7882       );
7883
7884       pr "\n"
7885   ) all_functions
7886
7887 and generate_perl_struct_list_code typ cols name style n do_cleanups =
7888   pr "PREINIT:\n";
7889   pr "      struct guestfs_%s_list *%s;\n" typ n;
7890   pr "      int i;\n";
7891   pr "      HV *hv;\n";
7892   pr " PPCODE:\n";
7893   pr "      %s = guestfs_%s " n name;
7894   generate_c_call_args ~handle:"g" style;
7895   pr ";\n";
7896   do_cleanups ();
7897   pr "      if (%s == NULL)\n" n;
7898   pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7899   pr "      EXTEND (SP, %s->len);\n" n;
7900   pr "      for (i = 0; i < %s->len; ++i) {\n" n;
7901   pr "        hv = newHV ();\n";
7902   List.iter (
7903     function
7904     | name, FString ->
7905         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
7906           name (String.length name) n name
7907     | name, FUUID ->
7908         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
7909           name (String.length name) n name
7910     | name, FBuffer ->
7911         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
7912           name (String.length name) n name n name
7913     | name, (FBytes|FUInt64) ->
7914         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
7915           name (String.length name) n name
7916     | name, FInt64 ->
7917         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
7918           name (String.length name) n name
7919     | name, (FInt32|FUInt32) ->
7920         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
7921           name (String.length name) n name
7922     | name, FChar ->
7923         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
7924           name (String.length name) n name
7925     | name, FOptPercent ->
7926         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
7927           name (String.length name) n name
7928   ) cols;
7929   pr "        PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
7930   pr "      }\n";
7931   pr "      guestfs_free_%s_list (%s);\n" typ n
7932
7933 and generate_perl_struct_code typ cols name style n do_cleanups =
7934   pr "PREINIT:\n";
7935   pr "      struct guestfs_%s *%s;\n" typ n;
7936   pr " PPCODE:\n";
7937   pr "      %s = guestfs_%s " n name;
7938   generate_c_call_args ~handle:"g" style;
7939   pr ";\n";
7940   do_cleanups ();
7941   pr "      if (%s == NULL)\n" n;
7942   pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7943   pr "      EXTEND (SP, 2 * %d);\n" (List.length cols);
7944   List.iter (
7945     fun ((name, _) as col) ->
7946       pr "      PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
7947
7948       match col with
7949       | name, FString ->
7950           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
7951             n name
7952       | name, FBuffer ->
7953           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, %s->%s_len)));\n"
7954             n name n name
7955       | name, FUUID ->
7956           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
7957             n name
7958       | name, (FBytes|FUInt64) ->
7959           pr "      PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
7960             n name
7961       | name, FInt64 ->
7962           pr "      PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
7963             n name
7964       | name, (FInt32|FUInt32) ->
7965           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
7966             n name
7967       | name, FChar ->
7968           pr "      PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
7969             n name
7970       | name, FOptPercent ->
7971           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
7972             n name
7973   ) cols;
7974   pr "      free (%s);\n" n
7975
7976 (* Generate Sys/Guestfs.pm. *)
7977 and generate_perl_pm () =
7978   generate_header HashStyle LGPLv2;
7979
7980   pr "\
7981 =pod
7982
7983 =head1 NAME
7984
7985 Sys::Guestfs - Perl bindings for libguestfs
7986
7987 =head1 SYNOPSIS
7988
7989  use Sys::Guestfs;
7990
7991  my $h = Sys::Guestfs->new ();
7992  $h->add_drive ('guest.img');
7993  $h->launch ();
7994  $h->mount ('/dev/sda1', '/');
7995  $h->touch ('/hello');
7996  $h->sync ();
7997
7998 =head1 DESCRIPTION
7999
8000 The C<Sys::Guestfs> module provides a Perl XS binding to the
8001 libguestfs API for examining and modifying virtual machine
8002 disk images.
8003
8004 Amongst the things this is good for: making batch configuration
8005 changes to guests, getting disk used/free statistics (see also:
8006 virt-df), migrating between virtualization systems (see also:
8007 virt-p2v), performing partial backups, performing partial guest
8008 clones, cloning guests and changing registry/UUID/hostname info, and
8009 much else besides.
8010
8011 Libguestfs uses Linux kernel and qemu code, and can access any type of
8012 guest filesystem that Linux and qemu can, including but not limited
8013 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8014 schemes, qcow, qcow2, vmdk.
8015
8016 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8017 LVs, what filesystem is in each LV, etc.).  It can also run commands
8018 in the context of the guest.  Also you can access filesystems over FTP.
8019
8020 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
8021 functions for using libguestfs from Perl, including integration
8022 with libvirt.
8023
8024 =head1 ERRORS
8025
8026 All errors turn into calls to C<croak> (see L<Carp(3)>).
8027
8028 =head1 METHODS
8029
8030 =over 4
8031
8032 =cut
8033
8034 package Sys::Guestfs;
8035
8036 use strict;
8037 use warnings;
8038
8039 require XSLoader;
8040 XSLoader::load ('Sys::Guestfs');
8041
8042 =item $h = Sys::Guestfs->new ();
8043
8044 Create a new guestfs handle.
8045
8046 =cut
8047
8048 sub new {
8049   my $proto = shift;
8050   my $class = ref ($proto) || $proto;
8051
8052   my $self = Sys::Guestfs::_create ();
8053   bless $self, $class;
8054   return $self;
8055 }
8056
8057 ";
8058
8059   (* Actions.  We only need to print documentation for these as
8060    * they are pulled in from the XS code automatically.
8061    *)
8062   List.iter (
8063     fun (name, style, _, flags, _, _, longdesc) ->
8064       if not (List.mem NotInDocs flags) then (
8065         let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
8066         pr "=item ";
8067         generate_perl_prototype name style;
8068         pr "\n\n";
8069         pr "%s\n\n" longdesc;
8070         if List.mem ProtocolLimitWarning flags then
8071           pr "%s\n\n" protocol_limit_warning;
8072         if List.mem DangerWillRobinson flags then
8073           pr "%s\n\n" danger_will_robinson;
8074         match deprecation_notice flags with
8075         | None -> ()
8076         | Some txt -> pr "%s\n\n" txt
8077       )
8078   ) all_functions_sorted;
8079
8080   (* End of file. *)
8081   pr "\
8082 =cut
8083
8084 1;
8085
8086 =back
8087
8088 =head1 COPYRIGHT
8089
8090 Copyright (C) 2009 Red Hat Inc.
8091
8092 =head1 LICENSE
8093
8094 Please see the file COPYING.LIB for the full license.
8095
8096 =head1 SEE ALSO
8097
8098 L<guestfs(3)>,
8099 L<guestfish(1)>,
8100 L<http://libguestfs.org>,
8101 L<Sys::Guestfs::Lib(3)>.
8102
8103 =cut
8104 "
8105
8106 and generate_perl_prototype name style =
8107   (match fst style with
8108    | RErr -> ()
8109    | RBool n
8110    | RInt n
8111    | RInt64 n
8112    | RConstString n
8113    | RConstOptString n
8114    | RString n
8115    | RBufferOut n -> pr "$%s = " n
8116    | RStruct (n,_)
8117    | RHashtable n -> pr "%%%s = " n
8118    | RStringList n
8119    | RStructList (n,_) -> pr "@%s = " n
8120   );
8121   pr "$h->%s (" name;
8122   let comma = ref false in
8123   List.iter (
8124     fun arg ->
8125       if !comma then pr ", ";
8126       comma := true;
8127       match arg with
8128       | Pathname n | Device n | Dev_or_Path n | String n
8129       | OptString n | Bool n | Int n | Int64 n | FileIn n | FileOut n ->
8130           pr "$%s" n
8131       | StringList n | DeviceList n ->
8132           pr "\\@%s" n
8133   ) (snd style);
8134   pr ");"
8135
8136 (* Generate Python C module. *)
8137 and generate_python_c () =
8138   generate_header CStyle LGPLv2;
8139
8140   pr "\
8141 #include <Python.h>
8142
8143 #include <stdio.h>
8144 #include <stdlib.h>
8145 #include <assert.h>
8146
8147 #include \"guestfs.h\"
8148
8149 typedef struct {
8150   PyObject_HEAD
8151   guestfs_h *g;
8152 } Pyguestfs_Object;
8153
8154 static guestfs_h *
8155 get_handle (PyObject *obj)
8156 {
8157   assert (obj);
8158   assert (obj != Py_None);
8159   return ((Pyguestfs_Object *) obj)->g;
8160 }
8161
8162 static PyObject *
8163 put_handle (guestfs_h *g)
8164 {
8165   assert (g);
8166   return
8167     PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
8168 }
8169
8170 /* This list should be freed (but not the strings) after use. */
8171 static char **
8172 get_string_list (PyObject *obj)
8173 {
8174   int i, len;
8175   char **r;
8176
8177   assert (obj);
8178
8179   if (!PyList_Check (obj)) {
8180     PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
8181     return NULL;
8182   }
8183
8184   len = PyList_Size (obj);
8185   r = malloc (sizeof (char *) * (len+1));
8186   if (r == NULL) {
8187     PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
8188     return NULL;
8189   }
8190
8191   for (i = 0; i < len; ++i)
8192     r[i] = PyString_AsString (PyList_GetItem (obj, i));
8193   r[len] = NULL;
8194
8195   return r;
8196 }
8197
8198 static PyObject *
8199 put_string_list (char * const * const argv)
8200 {
8201   PyObject *list;
8202   int argc, i;
8203
8204   for (argc = 0; argv[argc] != NULL; ++argc)
8205     ;
8206
8207   list = PyList_New (argc);
8208   for (i = 0; i < argc; ++i)
8209     PyList_SetItem (list, i, PyString_FromString (argv[i]));
8210
8211   return list;
8212 }
8213
8214 static PyObject *
8215 put_table (char * const * const argv)
8216 {
8217   PyObject *list, *item;
8218   int argc, i;
8219
8220   for (argc = 0; argv[argc] != NULL; ++argc)
8221     ;
8222
8223   list = PyList_New (argc >> 1);
8224   for (i = 0; i < argc; i += 2) {
8225     item = PyTuple_New (2);
8226     PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
8227     PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
8228     PyList_SetItem (list, i >> 1, item);
8229   }
8230
8231   return list;
8232 }
8233
8234 static void
8235 free_strings (char **argv)
8236 {
8237   int argc;
8238
8239   for (argc = 0; argv[argc] != NULL; ++argc)
8240     free (argv[argc]);
8241   free (argv);
8242 }
8243
8244 static PyObject *
8245 py_guestfs_create (PyObject *self, PyObject *args)
8246 {
8247   guestfs_h *g;
8248
8249   g = guestfs_create ();
8250   if (g == NULL) {
8251     PyErr_SetString (PyExc_RuntimeError,
8252                      \"guestfs.create: failed to allocate handle\");
8253     return NULL;
8254   }
8255   guestfs_set_error_handler (g, NULL, NULL);
8256   return put_handle (g);
8257 }
8258
8259 static PyObject *
8260 py_guestfs_close (PyObject *self, PyObject *args)
8261 {
8262   PyObject *py_g;
8263   guestfs_h *g;
8264
8265   if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
8266     return NULL;
8267   g = get_handle (py_g);
8268
8269   guestfs_close (g);
8270
8271   Py_INCREF (Py_None);
8272   return Py_None;
8273 }
8274
8275 ";
8276
8277   let emit_put_list_function typ =
8278     pr "static PyObject *\n";
8279     pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
8280     pr "{\n";
8281     pr "  PyObject *list;\n";
8282     pr "  int i;\n";
8283     pr "\n";
8284     pr "  list = PyList_New (%ss->len);\n" typ;
8285     pr "  for (i = 0; i < %ss->len; ++i)\n" typ;
8286     pr "    PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
8287     pr "  return list;\n";
8288     pr "};\n";
8289     pr "\n"
8290   in
8291
8292   (* Structures, turned into Python dictionaries. *)
8293   List.iter (
8294     fun (typ, cols) ->
8295       pr "static PyObject *\n";
8296       pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
8297       pr "{\n";
8298       pr "  PyObject *dict;\n";
8299       pr "\n";
8300       pr "  dict = PyDict_New ();\n";
8301       List.iter (
8302         function
8303         | name, FString ->
8304             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8305             pr "                        PyString_FromString (%s->%s));\n"
8306               typ name
8307         | name, FBuffer ->
8308             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8309             pr "                        PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
8310               typ name typ name
8311         | name, FUUID ->
8312             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8313             pr "                        PyString_FromStringAndSize (%s->%s, 32));\n"
8314               typ name
8315         | name, (FBytes|FUInt64) ->
8316             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8317             pr "                        PyLong_FromUnsignedLongLong (%s->%s));\n"
8318               typ name
8319         | name, FInt64 ->
8320             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8321             pr "                        PyLong_FromLongLong (%s->%s));\n"
8322               typ name
8323         | name, FUInt32 ->
8324             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8325             pr "                        PyLong_FromUnsignedLong (%s->%s));\n"
8326               typ name
8327         | name, FInt32 ->
8328             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8329             pr "                        PyLong_FromLong (%s->%s));\n"
8330               typ name
8331         | name, FOptPercent ->
8332             pr "  if (%s->%s >= 0)\n" typ name;
8333             pr "    PyDict_SetItemString (dict, \"%s\",\n" name;
8334             pr "                          PyFloat_FromDouble ((double) %s->%s));\n"
8335               typ name;
8336             pr "  else {\n";
8337             pr "    Py_INCREF (Py_None);\n";
8338             pr "    PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
8339             pr "  }\n"
8340         | name, FChar ->
8341             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8342             pr "                        PyString_FromStringAndSize (&dirent->%s, 1));\n" name
8343       ) cols;
8344       pr "  return dict;\n";
8345       pr "};\n";
8346       pr "\n";
8347
8348   ) structs;
8349
8350   (* Emit a put_TYPE_list function definition only if that function is used. *)
8351   List.iter (
8352     function
8353     | typ, (RStructListOnly | RStructAndList) ->
8354         (* generate the function for typ *)
8355         emit_put_list_function typ
8356     | typ, _ -> () (* empty *)
8357   ) (rstructs_used_by all_functions);
8358
8359   (* Python wrapper functions. *)
8360   List.iter (
8361     fun (name, style, _, _, _, _, _) ->
8362       pr "static PyObject *\n";
8363       pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
8364       pr "{\n";
8365
8366       pr "  PyObject *py_g;\n";
8367       pr "  guestfs_h *g;\n";
8368       pr "  PyObject *py_r;\n";
8369
8370       let error_code =
8371         match fst style with
8372         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
8373         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8374         | RConstString _ | RConstOptString _ ->
8375             pr "  const char *r;\n"; "NULL"
8376         | RString _ -> pr "  char *r;\n"; "NULL"
8377         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
8378         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
8379         | RStructList (_, typ) ->
8380             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8381         | RBufferOut _ ->
8382             pr "  char *r;\n";
8383             pr "  size_t size;\n";
8384             "NULL" in
8385
8386       List.iter (
8387         function
8388         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8389             pr "  const char *%s;\n" n
8390         | OptString n -> pr "  const char *%s;\n" n
8391         | StringList n | DeviceList n ->
8392             pr "  PyObject *py_%s;\n" n;
8393             pr "  char **%s;\n" n
8394         | Bool n -> pr "  int %s;\n" n
8395         | Int n -> pr "  int %s;\n" n
8396         | Int64 n -> pr "  long long %s;\n" n
8397       ) (snd style);
8398
8399       pr "\n";
8400
8401       (* Convert the parameters. *)
8402       pr "  if (!PyArg_ParseTuple (args, (char *) \"O";
8403       List.iter (
8404         function
8405         | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
8406         | OptString _ -> pr "z"
8407         | StringList _ | DeviceList _ -> pr "O"
8408         | Bool _ -> pr "i" (* XXX Python has booleans? *)
8409         | Int _ -> pr "i"
8410         | Int64 _ -> pr "L" (* XXX Whoever thought it was a good idea to
8411                              * emulate C's int/long/long long in Python?
8412                              *)
8413       ) (snd style);
8414       pr ":guestfs_%s\",\n" name;
8415       pr "                         &py_g";
8416       List.iter (
8417         function
8418         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
8419         | OptString n -> pr ", &%s" n
8420         | StringList n | DeviceList n -> pr ", &py_%s" n
8421         | Bool n -> pr ", &%s" n
8422         | Int n -> pr ", &%s" n
8423         | Int64 n -> pr ", &%s" n
8424       ) (snd style);
8425
8426       pr "))\n";
8427       pr "    return NULL;\n";
8428
8429       pr "  g = get_handle (py_g);\n";
8430       List.iter (
8431         function
8432         | Pathname _ | Device _ | Dev_or_Path _ | String _
8433         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
8434         | StringList n | DeviceList n ->
8435             pr "  %s = get_string_list (py_%s);\n" n n;
8436             pr "  if (!%s) return NULL;\n" n
8437       ) (snd style);
8438
8439       pr "\n";
8440
8441       pr "  r = guestfs_%s " name;
8442       generate_c_call_args ~handle:"g" style;
8443       pr ";\n";
8444
8445       List.iter (
8446         function
8447         | Pathname _ | Device _ | Dev_or_Path _ | String _
8448         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
8449         | StringList n | DeviceList n ->
8450             pr "  free (%s);\n" n
8451       ) (snd style);
8452
8453       pr "  if (r == %s) {\n" error_code;
8454       pr "    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
8455       pr "    return NULL;\n";
8456       pr "  }\n";
8457       pr "\n";
8458
8459       (match fst style with
8460        | RErr ->
8461            pr "  Py_INCREF (Py_None);\n";
8462            pr "  py_r = Py_None;\n"
8463        | RInt _
8464        | RBool _ -> pr "  py_r = PyInt_FromLong ((long) r);\n"
8465        | RInt64 _ -> pr "  py_r = PyLong_FromLongLong (r);\n"
8466        | RConstString _ -> pr "  py_r = PyString_FromString (r);\n"
8467        | RConstOptString _ ->
8468            pr "  if (r)\n";
8469            pr "    py_r = PyString_FromString (r);\n";
8470            pr "  else {\n";
8471            pr "    Py_INCREF (Py_None);\n";
8472            pr "    py_r = Py_None;\n";
8473            pr "  }\n"
8474        | RString _ ->
8475            pr "  py_r = PyString_FromString (r);\n";
8476            pr "  free (r);\n"
8477        | RStringList _ ->
8478            pr "  py_r = put_string_list (r);\n";
8479            pr "  free_strings (r);\n"
8480        | RStruct (_, typ) ->
8481            pr "  py_r = put_%s (r);\n" typ;
8482            pr "  guestfs_free_%s (r);\n" typ
8483        | RStructList (_, typ) ->
8484            pr "  py_r = put_%s_list (r);\n" typ;
8485            pr "  guestfs_free_%s_list (r);\n" typ
8486        | RHashtable n ->
8487            pr "  py_r = put_table (r);\n";
8488            pr "  free_strings (r);\n"
8489        | RBufferOut _ ->
8490            pr "  py_r = PyString_FromStringAndSize (r, size);\n";
8491            pr "  free (r);\n"
8492       );
8493
8494       pr "  return py_r;\n";
8495       pr "}\n";
8496       pr "\n"
8497   ) all_functions;
8498
8499   (* Table of functions. *)
8500   pr "static PyMethodDef methods[] = {\n";
8501   pr "  { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
8502   pr "  { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
8503   List.iter (
8504     fun (name, _, _, _, _, _, _) ->
8505       pr "  { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
8506         name name
8507   ) all_functions;
8508   pr "  { NULL, NULL, 0, NULL }\n";
8509   pr "};\n";
8510   pr "\n";
8511
8512   (* Init function. *)
8513   pr "\
8514 void
8515 initlibguestfsmod (void)
8516 {
8517   static int initialized = 0;
8518
8519   if (initialized) return;
8520   Py_InitModule ((char *) \"libguestfsmod\", methods);
8521   initialized = 1;
8522 }
8523 "
8524
8525 (* Generate Python module. *)
8526 and generate_python_py () =
8527   generate_header HashStyle LGPLv2;
8528
8529   pr "\
8530 u\"\"\"Python bindings for libguestfs
8531
8532 import guestfs
8533 g = guestfs.GuestFS ()
8534 g.add_drive (\"guest.img\")
8535 g.launch ()
8536 parts = g.list_partitions ()
8537
8538 The guestfs module provides a Python binding to the libguestfs API
8539 for examining and modifying virtual machine disk images.
8540
8541 Amongst the things this is good for: making batch configuration
8542 changes to guests, getting disk used/free statistics (see also:
8543 virt-df), migrating between virtualization systems (see also:
8544 virt-p2v), performing partial backups, performing partial guest
8545 clones, cloning guests and changing registry/UUID/hostname info, and
8546 much else besides.
8547
8548 Libguestfs uses Linux kernel and qemu code, and can access any type of
8549 guest filesystem that Linux and qemu can, including but not limited
8550 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8551 schemes, qcow, qcow2, vmdk.
8552
8553 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8554 LVs, what filesystem is in each LV, etc.).  It can also run commands
8555 in the context of the guest.  Also you can access filesystems over FTP.
8556
8557 Errors which happen while using the API are turned into Python
8558 RuntimeError exceptions.
8559
8560 To create a guestfs handle you usually have to perform the following
8561 sequence of calls:
8562
8563 # Create the handle, call add_drive at least once, and possibly
8564 # several times if the guest has multiple block devices:
8565 g = guestfs.GuestFS ()
8566 g.add_drive (\"guest.img\")
8567
8568 # Launch the qemu subprocess and wait for it to become ready:
8569 g.launch ()
8570
8571 # Now you can issue commands, for example:
8572 logvols = g.lvs ()
8573
8574 \"\"\"
8575
8576 import libguestfsmod
8577
8578 class GuestFS:
8579     \"\"\"Instances of this class are libguestfs API handles.\"\"\"
8580
8581     def __init__ (self):
8582         \"\"\"Create a new libguestfs handle.\"\"\"
8583         self._o = libguestfsmod.create ()
8584
8585     def __del__ (self):
8586         libguestfsmod.close (self._o)
8587
8588 ";
8589
8590   List.iter (
8591     fun (name, style, _, flags, _, _, longdesc) ->
8592       pr "    def %s " name;
8593       generate_py_call_args ~handle:"self" (snd style);
8594       pr ":\n";
8595
8596       if not (List.mem NotInDocs flags) then (
8597         let doc = replace_str longdesc "C<guestfs_" "C<g." in
8598         let doc =
8599           match fst style with
8600           | RErr | RInt _ | RInt64 _ | RBool _
8601           | RConstOptString _ | RConstString _
8602           | RString _ | RBufferOut _ -> doc
8603           | RStringList _ ->
8604               doc ^ "\n\nThis function returns a list of strings."
8605           | RStruct (_, typ) ->
8606               doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
8607           | RStructList (_, typ) ->
8608               doc ^ sprintf "\n\nThis function returns a list of %ss.  Each %s is represented as a dictionary." typ typ
8609           | RHashtable _ ->
8610               doc ^ "\n\nThis function returns a dictionary." in
8611         let doc =
8612           if List.mem ProtocolLimitWarning flags then
8613             doc ^ "\n\n" ^ protocol_limit_warning
8614           else doc in
8615         let doc =
8616           if List.mem DangerWillRobinson flags then
8617             doc ^ "\n\n" ^ danger_will_robinson
8618           else doc in
8619         let doc =
8620           match deprecation_notice flags with
8621           | None -> doc
8622           | Some txt -> doc ^ "\n\n" ^ txt in
8623         let doc = pod2text ~width:60 name doc in
8624         let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
8625         let doc = String.concat "\n        " doc in
8626         pr "        u\"\"\"%s\"\"\"\n" doc;
8627       );
8628       pr "        return libguestfsmod.%s " name;
8629       generate_py_call_args ~handle:"self._o" (snd style);
8630       pr "\n";
8631       pr "\n";
8632   ) all_functions
8633
8634 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
8635 and generate_py_call_args ~handle args =
8636   pr "(%s" handle;
8637   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
8638   pr ")"
8639
8640 (* Useful if you need the longdesc POD text as plain text.  Returns a
8641  * list of lines.
8642  *
8643  * Because this is very slow (the slowest part of autogeneration),
8644  * we memoize the results.
8645  *)
8646 and pod2text ~width name longdesc =
8647   let key = width, name, longdesc in
8648   try Hashtbl.find pod2text_memo key
8649   with Not_found ->
8650     let filename, chan = Filename.open_temp_file "gen" ".tmp" in
8651     fprintf chan "=head1 %s\n\n%s\n" name longdesc;
8652     close_out chan;
8653     let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
8654     let chan = open_process_in cmd in
8655     let lines = ref [] in
8656     let rec loop i =
8657       let line = input_line chan in
8658       if i = 1 then             (* discard the first line of output *)
8659         loop (i+1)
8660       else (
8661         let line = triml line in
8662         lines := line :: !lines;
8663         loop (i+1)
8664       ) in
8665     let lines = try loop 1 with End_of_file -> List.rev !lines in
8666     unlink filename;
8667     (match close_process_in chan with
8668      | WEXITED 0 -> ()
8669      | WEXITED i ->
8670          failwithf "pod2text: process exited with non-zero status (%d)" i
8671      | WSIGNALED i | WSTOPPED i ->
8672          failwithf "pod2text: process signalled or stopped by signal %d" i
8673     );
8674     Hashtbl.add pod2text_memo key lines;
8675     pod2text_memo_updated ();
8676     lines
8677
8678 (* Generate ruby bindings. *)
8679 and generate_ruby_c () =
8680   generate_header CStyle LGPLv2;
8681
8682   pr "\
8683 #include <stdio.h>
8684 #include <stdlib.h>
8685
8686 #include <ruby.h>
8687
8688 #include \"guestfs.h\"
8689
8690 #include \"extconf.h\"
8691
8692 /* For Ruby < 1.9 */
8693 #ifndef RARRAY_LEN
8694 #define RARRAY_LEN(r) (RARRAY((r))->len)
8695 #endif
8696
8697 static VALUE m_guestfs;                 /* guestfs module */
8698 static VALUE c_guestfs;                 /* guestfs_h handle */
8699 static VALUE e_Error;                   /* used for all errors */
8700
8701 static void ruby_guestfs_free (void *p)
8702 {
8703   if (!p) return;
8704   guestfs_close ((guestfs_h *) p);
8705 }
8706
8707 static VALUE ruby_guestfs_create (VALUE m)
8708 {
8709   guestfs_h *g;
8710
8711   g = guestfs_create ();
8712   if (!g)
8713     rb_raise (e_Error, \"failed to create guestfs handle\");
8714
8715   /* Don't print error messages to stderr by default. */
8716   guestfs_set_error_handler (g, NULL, NULL);
8717
8718   /* Wrap it, and make sure the close function is called when the
8719    * handle goes away.
8720    */
8721   return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
8722 }
8723
8724 static VALUE ruby_guestfs_close (VALUE gv)
8725 {
8726   guestfs_h *g;
8727   Data_Get_Struct (gv, guestfs_h, g);
8728
8729   ruby_guestfs_free (g);
8730   DATA_PTR (gv) = NULL;
8731
8732   return Qnil;
8733 }
8734
8735 ";
8736
8737   List.iter (
8738     fun (name, style, _, _, _, _, _) ->
8739       pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
8740       List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
8741       pr ")\n";
8742       pr "{\n";
8743       pr "  guestfs_h *g;\n";
8744       pr "  Data_Get_Struct (gv, guestfs_h, g);\n";
8745       pr "  if (!g)\n";
8746       pr "    rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
8747         name;
8748       pr "\n";
8749
8750       List.iter (
8751         function
8752         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8753             pr "  Check_Type (%sv, T_STRING);\n" n;
8754             pr "  const char *%s = StringValueCStr (%sv);\n" n n;
8755             pr "  if (!%s)\n" n;
8756             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
8757             pr "              \"%s\", \"%s\");\n" n name
8758         | OptString n ->
8759             pr "  const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
8760         | StringList n | DeviceList n ->
8761             pr "  char **%s;\n" n;
8762             pr "  Check_Type (%sv, T_ARRAY);\n" n;
8763             pr "  {\n";
8764             pr "    int i, len;\n";
8765             pr "    len = RARRAY_LEN (%sv);\n" n;
8766             pr "    %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
8767               n;
8768             pr "    for (i = 0; i < len; ++i) {\n";
8769             pr "      VALUE v = rb_ary_entry (%sv, i);\n" n;
8770             pr "      %s[i] = StringValueCStr (v);\n" n;
8771             pr "    }\n";
8772             pr "    %s[len] = NULL;\n" n;
8773             pr "  }\n";
8774         | Bool n ->
8775             pr "  int %s = RTEST (%sv);\n" n n
8776         | Int n ->
8777             pr "  int %s = NUM2INT (%sv);\n" n n
8778         | Int64 n ->
8779             pr "  long long %s = NUM2LL (%sv);\n" n n
8780       ) (snd style);
8781       pr "\n";
8782
8783       let error_code =
8784         match fst style with
8785         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
8786         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8787         | RConstString _ | RConstOptString _ ->
8788             pr "  const char *r;\n"; "NULL"
8789         | RString _ -> pr "  char *r;\n"; "NULL"
8790         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
8791         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
8792         | RStructList (_, typ) ->
8793             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8794         | RBufferOut _ ->
8795             pr "  char *r;\n";
8796             pr "  size_t size;\n";
8797             "NULL" in
8798       pr "\n";
8799
8800       pr "  r = guestfs_%s " name;
8801       generate_c_call_args ~handle:"g" style;
8802       pr ";\n";
8803
8804       List.iter (
8805         function
8806         | Pathname _ | Device _ | Dev_or_Path _ | String _
8807         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
8808         | StringList n | DeviceList n ->
8809             pr "  free (%s);\n" n
8810       ) (snd style);
8811
8812       pr "  if (r == %s)\n" error_code;
8813       pr "    rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
8814       pr "\n";
8815
8816       (match fst style with
8817        | RErr ->
8818            pr "  return Qnil;\n"
8819        | RInt _ | RBool _ ->
8820            pr "  return INT2NUM (r);\n"
8821        | RInt64 _ ->
8822            pr "  return ULL2NUM (r);\n"
8823        | RConstString _ ->
8824            pr "  return rb_str_new2 (r);\n";
8825        | RConstOptString _ ->
8826            pr "  if (r)\n";
8827            pr "    return rb_str_new2 (r);\n";
8828            pr "  else\n";
8829            pr "    return Qnil;\n";
8830        | RString _ ->
8831            pr "  VALUE rv = rb_str_new2 (r);\n";
8832            pr "  free (r);\n";
8833            pr "  return rv;\n";
8834        | RStringList _ ->
8835            pr "  int i, len = 0;\n";
8836            pr "  for (i = 0; r[i] != NULL; ++i) len++;\n";
8837            pr "  VALUE rv = rb_ary_new2 (len);\n";
8838            pr "  for (i = 0; r[i] != NULL; ++i) {\n";
8839            pr "    rb_ary_push (rv, rb_str_new2 (r[i]));\n";
8840            pr "    free (r[i]);\n";
8841            pr "  }\n";
8842            pr "  free (r);\n";
8843            pr "  return rv;\n"
8844        | RStruct (_, typ) ->
8845            let cols = cols_of_struct typ in
8846            generate_ruby_struct_code typ cols
8847        | RStructList (_, typ) ->
8848            let cols = cols_of_struct typ in
8849            generate_ruby_struct_list_code typ cols
8850        | RHashtable _ ->
8851            pr "  VALUE rv = rb_hash_new ();\n";
8852            pr "  int i;\n";
8853            pr "  for (i = 0; r[i] != NULL; i+=2) {\n";
8854            pr "    rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
8855            pr "    free (r[i]);\n";
8856            pr "    free (r[i+1]);\n";
8857            pr "  }\n";
8858            pr "  free (r);\n";
8859            pr "  return rv;\n"
8860        | RBufferOut _ ->
8861            pr "  VALUE rv = rb_str_new (r, size);\n";
8862            pr "  free (r);\n";
8863            pr "  return rv;\n";
8864       );
8865
8866       pr "}\n";
8867       pr "\n"
8868   ) all_functions;
8869
8870   pr "\
8871 /* Initialize the module. */
8872 void Init__guestfs ()
8873 {
8874   m_guestfs = rb_define_module (\"Guestfs\");
8875   c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
8876   e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
8877
8878   rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
8879   rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
8880
8881 ";
8882   (* Define the rest of the methods. *)
8883   List.iter (
8884     fun (name, style, _, _, _, _, _) ->
8885       pr "  rb_define_method (c_guestfs, \"%s\",\n" name;
8886       pr "        ruby_guestfs_%s, %d);\n" name (List.length (snd style))
8887   ) all_functions;
8888
8889   pr "}\n"
8890
8891 (* Ruby code to return a struct. *)
8892 and generate_ruby_struct_code typ cols =
8893   pr "  VALUE rv = rb_hash_new ();\n";
8894   List.iter (
8895     function
8896     | name, FString ->
8897         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
8898     | name, FBuffer ->
8899         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
8900     | name, FUUID ->
8901         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
8902     | name, (FBytes|FUInt64) ->
8903         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
8904     | name, FInt64 ->
8905         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
8906     | name, FUInt32 ->
8907         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
8908     | name, FInt32 ->
8909         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
8910     | name, FOptPercent ->
8911         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
8912     | name, FChar -> (* XXX wrong? *)
8913         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
8914   ) cols;
8915   pr "  guestfs_free_%s (r);\n" typ;
8916   pr "  return rv;\n"
8917
8918 (* Ruby code to return a struct list. *)
8919 and generate_ruby_struct_list_code typ cols =
8920   pr "  VALUE rv = rb_ary_new2 (r->len);\n";
8921   pr "  int i;\n";
8922   pr "  for (i = 0; i < r->len; ++i) {\n";
8923   pr "    VALUE hv = rb_hash_new ();\n";
8924   List.iter (
8925     function
8926     | name, FString ->
8927         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
8928     | name, FBuffer ->
8929         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
8930     | name, FUUID ->
8931         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
8932     | name, (FBytes|FUInt64) ->
8933         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
8934     | name, FInt64 ->
8935         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
8936     | name, FUInt32 ->
8937         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
8938     | name, FInt32 ->
8939         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
8940     | name, FOptPercent ->
8941         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
8942     | name, FChar -> (* XXX wrong? *)
8943         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
8944   ) cols;
8945   pr "    rb_ary_push (rv, hv);\n";
8946   pr "  }\n";
8947   pr "  guestfs_free_%s_list (r);\n" typ;
8948   pr "  return rv;\n"
8949
8950 (* Generate Java bindings GuestFS.java file. *)
8951 and generate_java_java () =
8952   generate_header CStyle LGPLv2;
8953
8954   pr "\
8955 package com.redhat.et.libguestfs;
8956
8957 import java.util.HashMap;
8958 import com.redhat.et.libguestfs.LibGuestFSException;
8959 import com.redhat.et.libguestfs.PV;
8960 import com.redhat.et.libguestfs.VG;
8961 import com.redhat.et.libguestfs.LV;
8962 import com.redhat.et.libguestfs.Stat;
8963 import com.redhat.et.libguestfs.StatVFS;
8964 import com.redhat.et.libguestfs.IntBool;
8965 import com.redhat.et.libguestfs.Dirent;
8966
8967 /**
8968  * The GuestFS object is a libguestfs handle.
8969  *
8970  * @author rjones
8971  */
8972 public class GuestFS {
8973   // Load the native code.
8974   static {
8975     System.loadLibrary (\"guestfs_jni\");
8976   }
8977
8978   /**
8979    * The native guestfs_h pointer.
8980    */
8981   long g;
8982
8983   /**
8984    * Create a libguestfs handle.
8985    *
8986    * @throws LibGuestFSException
8987    */
8988   public GuestFS () throws LibGuestFSException
8989   {
8990     g = _create ();
8991   }
8992   private native long _create () throws LibGuestFSException;
8993
8994   /**
8995    * Close a libguestfs handle.
8996    *
8997    * You can also leave handles to be collected by the garbage
8998    * collector, but this method ensures that the resources used
8999    * by the handle are freed up immediately.  If you call any
9000    * other methods after closing the handle, you will get an
9001    * exception.
9002    *
9003    * @throws LibGuestFSException
9004    */
9005   public void close () throws LibGuestFSException
9006   {
9007     if (g != 0)
9008       _close (g);
9009     g = 0;
9010   }
9011   private native void _close (long g) throws LibGuestFSException;
9012
9013   public void finalize () throws LibGuestFSException
9014   {
9015     close ();
9016   }
9017
9018 ";
9019
9020   List.iter (
9021     fun (name, style, _, flags, _, shortdesc, longdesc) ->
9022       if not (List.mem NotInDocs flags); then (
9023         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9024         let doc =
9025           if List.mem ProtocolLimitWarning flags then
9026             doc ^ "\n\n" ^ protocol_limit_warning
9027           else doc in
9028         let doc =
9029           if List.mem DangerWillRobinson flags then
9030             doc ^ "\n\n" ^ danger_will_robinson
9031           else doc in
9032         let doc =
9033           match deprecation_notice flags with
9034           | None -> doc
9035           | Some txt -> doc ^ "\n\n" ^ txt in
9036         let doc = pod2text ~width:60 name doc in
9037         let doc = List.map (            (* RHBZ#501883 *)
9038           function
9039           | "" -> "<p>"
9040           | nonempty -> nonempty
9041         ) doc in
9042         let doc = String.concat "\n   * " doc in
9043
9044         pr "  /**\n";
9045         pr "   * %s\n" shortdesc;
9046         pr "   * <p>\n";
9047         pr "   * %s\n" doc;
9048         pr "   * @throws LibGuestFSException\n";
9049         pr "   */\n";
9050         pr "  ";
9051       );
9052       generate_java_prototype ~public:true ~semicolon:false name style;
9053       pr "\n";
9054       pr "  {\n";
9055       pr "    if (g == 0)\n";
9056       pr "      throw new LibGuestFSException (\"%s: handle is closed\");\n"
9057         name;
9058       pr "    ";
9059       if fst style <> RErr then pr "return ";
9060       pr "_%s " name;
9061       generate_java_call_args ~handle:"g" (snd style);
9062       pr ";\n";
9063       pr "  }\n";
9064       pr "  ";
9065       generate_java_prototype ~privat:true ~native:true name style;
9066       pr "\n";
9067       pr "\n";
9068   ) all_functions;
9069
9070   pr "}\n"
9071
9072 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
9073 and generate_java_call_args ~handle args =
9074   pr "(%s" handle;
9075   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9076   pr ")"
9077
9078 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
9079     ?(semicolon=true) name style =
9080   if privat then pr "private ";
9081   if public then pr "public ";
9082   if native then pr "native ";
9083
9084   (* return type *)
9085   (match fst style with
9086    | RErr -> pr "void ";
9087    | RInt _ -> pr "int ";
9088    | RInt64 _ -> pr "long ";
9089    | RBool _ -> pr "boolean ";
9090    | RConstString _ | RConstOptString _ | RString _
9091    | RBufferOut _ -> pr "String ";
9092    | RStringList _ -> pr "String[] ";
9093    | RStruct (_, typ) ->
9094        let name = java_name_of_struct typ in
9095        pr "%s " name;
9096    | RStructList (_, typ) ->
9097        let name = java_name_of_struct typ in
9098        pr "%s[] " name;
9099    | RHashtable _ -> pr "HashMap<String,String> ";
9100   );
9101
9102   if native then pr "_%s " name else pr "%s " name;
9103   pr "(";
9104   let needs_comma = ref false in
9105   if native then (
9106     pr "long g";
9107     needs_comma := true
9108   );
9109
9110   (* args *)
9111   List.iter (
9112     fun arg ->
9113       if !needs_comma then pr ", ";
9114       needs_comma := true;
9115
9116       match arg with
9117       | Pathname n
9118       | Device n | Dev_or_Path n
9119       | String n
9120       | OptString n
9121       | FileIn n
9122       | FileOut n ->
9123           pr "String %s" n
9124       | StringList n | DeviceList n ->
9125           pr "String[] %s" n
9126       | Bool n ->
9127           pr "boolean %s" n
9128       | Int n ->
9129           pr "int %s" n
9130       | Int64 n ->
9131           pr "long %s" n
9132   ) (snd style);
9133
9134   pr ")\n";
9135   pr "    throws LibGuestFSException";
9136   if semicolon then pr ";"
9137
9138 and generate_java_struct jtyp cols =
9139   generate_header CStyle LGPLv2;
9140
9141   pr "\
9142 package com.redhat.et.libguestfs;
9143
9144 /**
9145  * Libguestfs %s structure.
9146  *
9147  * @author rjones
9148  * @see GuestFS
9149  */
9150 public class %s {
9151 " jtyp jtyp;
9152
9153   List.iter (
9154     function
9155     | name, FString
9156     | name, FUUID
9157     | name, FBuffer -> pr "  public String %s;\n" name
9158     | name, (FBytes|FUInt64|FInt64) -> pr "  public long %s;\n" name
9159     | name, (FUInt32|FInt32) -> pr "  public int %s;\n" name
9160     | name, FChar -> pr "  public char %s;\n" name
9161     | name, FOptPercent ->
9162         pr "  /* The next field is [0..100] or -1 meaning 'not present': */\n";
9163         pr "  public float %s;\n" name
9164   ) cols;
9165
9166   pr "}\n"
9167
9168 and generate_java_c () =
9169   generate_header CStyle LGPLv2;
9170
9171   pr "\
9172 #include <stdio.h>
9173 #include <stdlib.h>
9174 #include <string.h>
9175
9176 #include \"com_redhat_et_libguestfs_GuestFS.h\"
9177 #include \"guestfs.h\"
9178
9179 /* Note that this function returns.  The exception is not thrown
9180  * until after the wrapper function returns.
9181  */
9182 static void
9183 throw_exception (JNIEnv *env, const char *msg)
9184 {
9185   jclass cl;
9186   cl = (*env)->FindClass (env,
9187                           \"com/redhat/et/libguestfs/LibGuestFSException\");
9188   (*env)->ThrowNew (env, cl, msg);
9189 }
9190
9191 JNIEXPORT jlong JNICALL
9192 Java_com_redhat_et_libguestfs_GuestFS__1create
9193   (JNIEnv *env, jobject obj)
9194 {
9195   guestfs_h *g;
9196
9197   g = guestfs_create ();
9198   if (g == NULL) {
9199     throw_exception (env, \"GuestFS.create: failed to allocate handle\");
9200     return 0;
9201   }
9202   guestfs_set_error_handler (g, NULL, NULL);
9203   return (jlong) (long) g;
9204 }
9205
9206 JNIEXPORT void JNICALL
9207 Java_com_redhat_et_libguestfs_GuestFS__1close
9208   (JNIEnv *env, jobject obj, jlong jg)
9209 {
9210   guestfs_h *g = (guestfs_h *) (long) jg;
9211   guestfs_close (g);
9212 }
9213
9214 ";
9215
9216   List.iter (
9217     fun (name, style, _, _, _, _, _) ->
9218       pr "JNIEXPORT ";
9219       (match fst style with
9220        | RErr -> pr "void ";
9221        | RInt _ -> pr "jint ";
9222        | RInt64 _ -> pr "jlong ";
9223        | RBool _ -> pr "jboolean ";
9224        | RConstString _ | RConstOptString _ | RString _
9225        | RBufferOut _ -> pr "jstring ";
9226        | RStruct _ | RHashtable _ ->
9227            pr "jobject ";
9228        | RStringList _ | RStructList _ ->
9229            pr "jobjectArray ";
9230       );
9231       pr "JNICALL\n";
9232       pr "Java_com_redhat_et_libguestfs_GuestFS_";
9233       pr "%s" (replace_str ("_" ^ name) "_" "_1");
9234       pr "\n";
9235       pr "  (JNIEnv *env, jobject obj, jlong jg";
9236       List.iter (
9237         function
9238         | Pathname n
9239         | Device n | Dev_or_Path n
9240         | String n
9241         | OptString n
9242         | FileIn n
9243         | FileOut n ->
9244             pr ", jstring j%s" n
9245         | StringList n | DeviceList n ->
9246             pr ", jobjectArray j%s" n
9247         | Bool n ->
9248             pr ", jboolean j%s" n
9249         | Int n ->
9250             pr ", jint j%s" n
9251         | Int64 n ->
9252             pr ", jlong j%s" n
9253       ) (snd style);
9254       pr ")\n";
9255       pr "{\n";
9256       pr "  guestfs_h *g = (guestfs_h *) (long) jg;\n";
9257       let error_code, no_ret =
9258         match fst style with
9259         | RErr -> pr "  int r;\n"; "-1", ""
9260         | RBool _
9261         | RInt _ -> pr "  int r;\n"; "-1", "0"
9262         | RInt64 _ -> pr "  int64_t r;\n"; "-1", "0"
9263         | RConstString _ -> pr "  const char *r;\n"; "NULL", "NULL"
9264         | RConstOptString _ -> pr "  const char *r;\n"; "NULL", "NULL"
9265         | RString _ ->
9266             pr "  jstring jr;\n";
9267             pr "  char *r;\n"; "NULL", "NULL"
9268         | RStringList _ ->
9269             pr "  jobjectArray jr;\n";
9270             pr "  int r_len;\n";
9271             pr "  jclass cl;\n";
9272             pr "  jstring jstr;\n";
9273             pr "  char **r;\n"; "NULL", "NULL"
9274         | RStruct (_, typ) ->
9275             pr "  jobject jr;\n";
9276             pr "  jclass cl;\n";
9277             pr "  jfieldID fl;\n";
9278             pr "  struct guestfs_%s *r;\n" typ; "NULL", "NULL"
9279         | RStructList (_, typ) ->
9280             pr "  jobjectArray jr;\n";
9281             pr "  jclass cl;\n";
9282             pr "  jfieldID fl;\n";
9283             pr "  jobject jfl;\n";
9284             pr "  struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
9285         | RHashtable _ -> pr "  char **r;\n"; "NULL", "NULL"
9286         | RBufferOut _ ->
9287             pr "  jstring jr;\n";
9288             pr "  char *r;\n";
9289             pr "  size_t size;\n";
9290             "NULL", "NULL" in
9291       List.iter (
9292         function
9293         | Pathname n
9294         | Device n | Dev_or_Path n
9295         | String n
9296         | OptString n
9297         | FileIn n
9298         | FileOut n ->
9299             pr "  const char *%s;\n" n
9300         | StringList n | DeviceList n ->
9301             pr "  int %s_len;\n" n;
9302             pr "  const char **%s;\n" n
9303         | Bool n
9304         | Int n ->
9305             pr "  int %s;\n" n
9306         | Int64 n ->
9307             pr "  int64_t %s;\n" n
9308       ) (snd style);
9309
9310       let needs_i =
9311         (match fst style with
9312          | RStringList _ | RStructList _ -> true
9313          | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
9314          | RConstOptString _
9315          | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
9316           List.exists (function
9317                        | StringList _ -> true
9318                        | DeviceList _ -> true
9319                        | _ -> false) (snd style) in
9320       if needs_i then
9321         pr "  int i;\n";
9322
9323       pr "\n";
9324
9325       (* Get the parameters. *)
9326       List.iter (
9327         function
9328         | Pathname n
9329         | Device n | Dev_or_Path n
9330         | String n
9331         | FileIn n
9332         | FileOut n ->
9333             pr "  %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
9334         | OptString n ->
9335             (* This is completely undocumented, but Java null becomes
9336              * a NULL parameter.
9337              *)
9338             pr "  %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
9339         | StringList n | DeviceList n ->
9340             pr "  %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
9341             pr "  %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
9342             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
9343             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
9344               n;
9345             pr "    %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
9346             pr "  }\n";
9347             pr "  %s[%s_len] = NULL;\n" n n;
9348         | Bool n
9349         | Int n
9350         | Int64 n ->
9351             pr "  %s = j%s;\n" n n
9352       ) (snd style);
9353
9354       (* Make the call. *)
9355       pr "  r = guestfs_%s " name;
9356       generate_c_call_args ~handle:"g" style;
9357       pr ";\n";
9358
9359       (* Release the parameters. *)
9360       List.iter (
9361         function
9362         | Pathname n
9363         | Device n | Dev_or_Path n
9364         | String n
9365         | FileIn n
9366         | FileOut n ->
9367             pr "  (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
9368         | OptString n ->
9369             pr "  if (j%s)\n" n;
9370             pr "    (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
9371         | StringList n | DeviceList n ->
9372             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
9373             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
9374               n;
9375             pr "    (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
9376             pr "  }\n";
9377             pr "  free (%s);\n" n
9378         | Bool n
9379         | Int n
9380         | Int64 n -> ()
9381       ) (snd style);
9382
9383       (* Check for errors. *)
9384       pr "  if (r == %s) {\n" error_code;
9385       pr "    throw_exception (env, guestfs_last_error (g));\n";
9386       pr "    return %s;\n" no_ret;
9387       pr "  }\n";
9388
9389       (* Return value. *)
9390       (match fst style with
9391        | RErr -> ()
9392        | RInt _ -> pr "  return (jint) r;\n"
9393        | RBool _ -> pr "  return (jboolean) r;\n"
9394        | RInt64 _ -> pr "  return (jlong) r;\n"
9395        | RConstString _ -> pr "  return (*env)->NewStringUTF (env, r);\n"
9396        | RConstOptString _ ->
9397            pr "  return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
9398        | RString _ ->
9399            pr "  jr = (*env)->NewStringUTF (env, r);\n";
9400            pr "  free (r);\n";
9401            pr "  return jr;\n"
9402        | RStringList _ ->
9403            pr "  for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
9404            pr "  cl = (*env)->FindClass (env, \"java/lang/String\");\n";
9405            pr "  jstr = (*env)->NewStringUTF (env, \"\");\n";
9406            pr "  jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
9407            pr "  for (i = 0; i < r_len; ++i) {\n";
9408            pr "    jstr = (*env)->NewStringUTF (env, r[i]);\n";
9409            pr "    (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
9410            pr "    free (r[i]);\n";
9411            pr "  }\n";
9412            pr "  free (r);\n";
9413            pr "  return jr;\n"
9414        | RStruct (_, typ) ->
9415            let jtyp = java_name_of_struct typ in
9416            let cols = cols_of_struct typ in
9417            generate_java_struct_return typ jtyp cols
9418        | RStructList (_, typ) ->
9419            let jtyp = java_name_of_struct typ in
9420            let cols = cols_of_struct typ in
9421            generate_java_struct_list_return typ jtyp cols
9422        | RHashtable _ ->
9423            (* XXX *)
9424            pr "  throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
9425            pr "  return NULL;\n"
9426        | RBufferOut _ ->
9427            pr "  jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
9428            pr "  free (r);\n";
9429            pr "  return jr;\n"
9430       );
9431
9432       pr "}\n";
9433       pr "\n"
9434   ) all_functions
9435
9436 and generate_java_struct_return typ jtyp cols =
9437   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
9438   pr "  jr = (*env)->AllocObject (env, cl);\n";
9439   List.iter (
9440     function
9441     | name, FString ->
9442         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9443         pr "  (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
9444     | name, FUUID ->
9445         pr "  {\n";
9446         pr "    char s[33];\n";
9447         pr "    memcpy (s, r->%s, 32);\n" name;
9448         pr "    s[32] = 0;\n";
9449         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9450         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
9451         pr "  }\n";
9452     | name, FBuffer ->
9453         pr "  {\n";
9454         pr "    int len = r->%s_len;\n" name;
9455         pr "    char s[len+1];\n";
9456         pr "    memcpy (s, r->%s, len);\n" name;
9457         pr "    s[len] = 0;\n";
9458         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9459         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
9460         pr "  }\n";
9461     | name, (FBytes|FUInt64|FInt64) ->
9462         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
9463         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
9464     | name, (FUInt32|FInt32) ->
9465         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
9466         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
9467     | name, FOptPercent ->
9468         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
9469         pr "  (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
9470     | name, FChar ->
9471         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
9472         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
9473   ) cols;
9474   pr "  free (r);\n";
9475   pr "  return jr;\n"
9476
9477 and generate_java_struct_list_return typ jtyp cols =
9478   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
9479   pr "  jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
9480   pr "  for (i = 0; i < r->len; ++i) {\n";
9481   pr "    jfl = (*env)->AllocObject (env, cl);\n";
9482   List.iter (
9483     function
9484     | name, FString ->
9485         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9486         pr "    (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
9487     | name, FUUID ->
9488         pr "    {\n";
9489         pr "      char s[33];\n";
9490         pr "      memcpy (s, r->val[i].%s, 32);\n" name;
9491         pr "      s[32] = 0;\n";
9492         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9493         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
9494         pr "    }\n";
9495     | name, FBuffer ->
9496         pr "    {\n";
9497         pr "      int len = r->val[i].%s_len;\n" name;
9498         pr "      char s[len+1];\n";
9499         pr "      memcpy (s, r->val[i].%s, len);\n" name;
9500         pr "      s[len] = 0;\n";
9501         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9502         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
9503         pr "    }\n";
9504     | name, (FBytes|FUInt64|FInt64) ->
9505         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
9506         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
9507     | name, (FUInt32|FInt32) ->
9508         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
9509         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
9510     | name, FOptPercent ->
9511         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
9512         pr "    (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
9513     | name, FChar ->
9514         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
9515         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
9516   ) cols;
9517   pr "    (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
9518   pr "  }\n";
9519   pr "  guestfs_free_%s_list (r);\n" typ;
9520   pr "  return jr;\n"
9521
9522 and generate_java_makefile_inc () =
9523   generate_header HashStyle GPLv2;
9524
9525   pr "java_built_sources = \\\n";
9526   List.iter (
9527     fun (typ, jtyp) ->
9528         pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
9529   ) java_structs;
9530   pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
9531
9532 and generate_haskell_hs () =
9533   generate_header HaskellStyle LGPLv2;
9534
9535   (* XXX We only know how to generate partial FFI for Haskell
9536    * at the moment.  Please help out!
9537    *)
9538   let can_generate style =
9539     match style with
9540     | RErr, _
9541     | RInt _, _
9542     | RInt64 _, _ -> true
9543     | RBool _, _
9544     | RConstString _, _
9545     | RConstOptString _, _
9546     | RString _, _
9547     | RStringList _, _
9548     | RStruct _, _
9549     | RStructList _, _
9550     | RHashtable _, _
9551     | RBufferOut _, _ -> false in
9552
9553   pr "\
9554 {-# INCLUDE <guestfs.h> #-}
9555 {-# LANGUAGE ForeignFunctionInterface #-}
9556
9557 module Guestfs (
9558   create";
9559
9560   (* List out the names of the actions we want to export. *)
9561   List.iter (
9562     fun (name, style, _, _, _, _, _) ->
9563       if can_generate style then pr ",\n  %s" name
9564   ) all_functions;
9565
9566   pr "
9567   ) where
9568
9569 -- Unfortunately some symbols duplicate ones already present
9570 -- in Prelude.  We don't know which, so we hard-code a list
9571 -- here.
9572 import Prelude hiding (truncate)
9573
9574 import Foreign
9575 import Foreign.C
9576 import Foreign.C.Types
9577 import IO
9578 import Control.Exception
9579 import Data.Typeable
9580
9581 data GuestfsS = GuestfsS            -- represents the opaque C struct
9582 type GuestfsP = Ptr GuestfsS        -- guestfs_h *
9583 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
9584
9585 -- XXX define properly later XXX
9586 data PV = PV
9587 data VG = VG
9588 data LV = LV
9589 data IntBool = IntBool
9590 data Stat = Stat
9591 data StatVFS = StatVFS
9592 data Hashtable = Hashtable
9593
9594 foreign import ccall unsafe \"guestfs_create\" c_create
9595   :: IO GuestfsP
9596 foreign import ccall unsafe \"&guestfs_close\" c_close
9597   :: FunPtr (GuestfsP -> IO ())
9598 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
9599   :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
9600
9601 create :: IO GuestfsH
9602 create = do
9603   p <- c_create
9604   c_set_error_handler p nullPtr nullPtr
9605   h <- newForeignPtr c_close p
9606   return h
9607
9608 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
9609   :: GuestfsP -> IO CString
9610
9611 -- last_error :: GuestfsH -> IO (Maybe String)
9612 -- last_error h = do
9613 --   str <- withForeignPtr h (\\p -> c_last_error p)
9614 --   maybePeek peekCString str
9615
9616 last_error :: GuestfsH -> IO (String)
9617 last_error h = do
9618   str <- withForeignPtr h (\\p -> c_last_error p)
9619   if (str == nullPtr)
9620     then return \"no error\"
9621     else peekCString str
9622
9623 ";
9624
9625   (* Generate wrappers for each foreign function. *)
9626   List.iter (
9627     fun (name, style, _, _, _, _, _) ->
9628       if can_generate style then (
9629         pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
9630         pr "  :: ";
9631         generate_haskell_prototype ~handle:"GuestfsP" style;
9632         pr "\n";
9633         pr "\n";
9634         pr "%s :: " name;
9635         generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
9636         pr "\n";
9637         pr "%s %s = do\n" name
9638           (String.concat " " ("h" :: List.map name_of_argt (snd style)));
9639         pr "  r <- ";
9640         (* Convert pointer arguments using with* functions. *)
9641         List.iter (
9642           function
9643           | FileIn n
9644           | FileOut n
9645           | Pathname n | Device n | Dev_or_Path n | String n -> pr "withCString %s $ \\%s -> " n n
9646           | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
9647           | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
9648           | Bool _ | Int _ | Int64 _ -> ()
9649         ) (snd style);
9650         (* Convert integer arguments. *)
9651         let args =
9652           List.map (
9653             function
9654             | Bool n -> sprintf "(fromBool %s)" n
9655             | Int n -> sprintf "(fromIntegral %s)" n
9656             | Int64 n -> sprintf "(fromIntegral %s)" n
9657             | FileIn n | FileOut n
9658             | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
9659           ) (snd style) in
9660         pr "withForeignPtr h (\\p -> c_%s %s)\n" name
9661           (String.concat " " ("p" :: args));
9662         (match fst style with
9663          | RErr | RInt _ | RInt64 _ | RBool _ ->
9664              pr "  if (r == -1)\n";
9665              pr "    then do\n";
9666              pr "      err <- last_error h\n";
9667              pr "      fail err\n";
9668          | RConstString _ | RConstOptString _ | RString _
9669          | RStringList _ | RStruct _
9670          | RStructList _ | RHashtable _ | RBufferOut _ ->
9671              pr "  if (r == nullPtr)\n";
9672              pr "    then do\n";
9673              pr "      err <- last_error h\n";
9674              pr "      fail err\n";
9675         );
9676         (match fst style with
9677          | RErr ->
9678              pr "    else return ()\n"
9679          | RInt _ ->
9680              pr "    else return (fromIntegral r)\n"
9681          | RInt64 _ ->
9682              pr "    else return (fromIntegral r)\n"
9683          | RBool _ ->
9684              pr "    else return (toBool r)\n"
9685          | RConstString _
9686          | RConstOptString _
9687          | RString _
9688          | RStringList _
9689          | RStruct _
9690          | RStructList _
9691          | RHashtable _
9692          | RBufferOut _ ->
9693              pr "    else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
9694         );
9695         pr "\n";
9696       )
9697   ) all_functions
9698
9699 and generate_haskell_prototype ~handle ?(hs = false) style =
9700   pr "%s -> " handle;
9701   let string = if hs then "String" else "CString" in
9702   let int = if hs then "Int" else "CInt" in
9703   let bool = if hs then "Bool" else "CInt" in
9704   let int64 = if hs then "Integer" else "Int64" in
9705   List.iter (
9706     fun arg ->
9707       (match arg with
9708        | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
9709        | OptString _ -> if hs then pr "Maybe String" else pr "CString"
9710        | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
9711        | Bool _ -> pr "%s" bool
9712        | Int _ -> pr "%s" int
9713        | Int64 _ -> pr "%s" int
9714        | FileIn _ -> pr "%s" string
9715        | FileOut _ -> pr "%s" string
9716       );
9717       pr " -> ";
9718   ) (snd style);
9719   pr "IO (";
9720   (match fst style with
9721    | RErr -> if not hs then pr "CInt"
9722    | RInt _ -> pr "%s" int
9723    | RInt64 _ -> pr "%s" int64
9724    | RBool _ -> pr "%s" bool
9725    | RConstString _ -> pr "%s" string
9726    | RConstOptString _ -> pr "Maybe %s" string
9727    | RString _ -> pr "%s" string
9728    | RStringList _ -> pr "[%s]" string
9729    | RStruct (_, typ) ->
9730        let name = java_name_of_struct typ in
9731        pr "%s" name
9732    | RStructList (_, typ) ->
9733        let name = java_name_of_struct typ in
9734        pr "[%s]" name
9735    | RHashtable _ -> pr "Hashtable"
9736    | RBufferOut _ -> pr "%s" string
9737   );
9738   pr ")"
9739
9740 and generate_bindtests () =
9741   generate_header CStyle LGPLv2;
9742
9743   pr "\
9744 #include <stdio.h>
9745 #include <stdlib.h>
9746 #include <inttypes.h>
9747 #include <string.h>
9748
9749 #include \"guestfs.h\"
9750 #include \"guestfs-internal.h\"
9751 #include \"guestfs-internal-actions.h\"
9752 #include \"guestfs_protocol.h\"
9753
9754 #define error guestfs_error
9755 #define safe_calloc guestfs_safe_calloc
9756 #define safe_malloc guestfs_safe_malloc
9757
9758 static void
9759 print_strings (char *const *argv)
9760 {
9761   int argc;
9762
9763   printf (\"[\");
9764   for (argc = 0; argv[argc] != NULL; ++argc) {
9765     if (argc > 0) printf (\", \");
9766     printf (\"\\\"%%s\\\"\", argv[argc]);
9767   }
9768   printf (\"]\\n\");
9769 }
9770
9771 /* The test0 function prints its parameters to stdout. */
9772 ";
9773
9774   let test0, tests =
9775     match test_functions with
9776     | [] -> assert false
9777     | test0 :: tests -> test0, tests in
9778
9779   let () =
9780     let (name, style, _, _, _, _, _) = test0 in
9781     generate_prototype ~extern:false ~semicolon:false ~newline:true
9782       ~handle:"g" ~prefix:"guestfs__" name style;
9783     pr "{\n";
9784     List.iter (
9785       function
9786       | Pathname n
9787       | Device n | Dev_or_Path n
9788       | String n
9789       | FileIn n
9790       | FileOut n -> pr "  printf (\"%%s\\n\", %s);\n" n
9791       | OptString n -> pr "  printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
9792       | StringList n | DeviceList n -> pr "  print_strings (%s);\n" n
9793       | Bool n -> pr "  printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
9794       | Int n -> pr "  printf (\"%%d\\n\", %s);\n" n
9795       | Int64 n -> pr "  printf (\"%%\" PRIi64 \"\\n\", %s);\n" n
9796     ) (snd style);
9797     pr "  /* Java changes stdout line buffering so we need this: */\n";
9798     pr "  fflush (stdout);\n";
9799     pr "  return 0;\n";
9800     pr "}\n";
9801     pr "\n" in
9802
9803   List.iter (
9804     fun (name, style, _, _, _, _, _) ->
9805       if String.sub name (String.length name - 3) 3 <> "err" then (
9806         pr "/* Test normal return. */\n";
9807         generate_prototype ~extern:false ~semicolon:false ~newline:true
9808           ~handle:"g" ~prefix:"guestfs__" name style;
9809         pr "{\n";
9810         (match fst style with
9811          | RErr ->
9812              pr "  return 0;\n"
9813          | RInt _ ->
9814              pr "  int r;\n";
9815              pr "  sscanf (val, \"%%d\", &r);\n";
9816              pr "  return r;\n"
9817          | RInt64 _ ->
9818              pr "  int64_t r;\n";
9819              pr "  sscanf (val, \"%%\" SCNi64, &r);\n";
9820              pr "  return r;\n"
9821          | RBool _ ->
9822              pr "  return STREQ (val, \"true\");\n"
9823          | RConstString _
9824          | RConstOptString _ ->
9825              (* Can't return the input string here.  Return a static
9826               * string so we ensure we get a segfault if the caller
9827               * tries to free it.
9828               *)
9829              pr "  return \"static string\";\n"
9830          | RString _ ->
9831              pr "  return strdup (val);\n"
9832          | RStringList _ ->
9833              pr "  char **strs;\n";
9834              pr "  int n, i;\n";
9835              pr "  sscanf (val, \"%%d\", &n);\n";
9836              pr "  strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
9837              pr "  for (i = 0; i < n; ++i) {\n";
9838              pr "    strs[i] = safe_malloc (g, 16);\n";
9839              pr "    snprintf (strs[i], 16, \"%%d\", i);\n";
9840              pr "  }\n";
9841              pr "  strs[n] = NULL;\n";
9842              pr "  return strs;\n"
9843          | RStruct (_, typ) ->
9844              pr "  struct guestfs_%s *r;\n" typ;
9845              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
9846              pr "  return r;\n"
9847          | RStructList (_, typ) ->
9848              pr "  struct guestfs_%s_list *r;\n" typ;
9849              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
9850              pr "  sscanf (val, \"%%d\", &r->len);\n";
9851              pr "  r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
9852              pr "  return r;\n"
9853          | RHashtable _ ->
9854              pr "  char **strs;\n";
9855              pr "  int n, i;\n";
9856              pr "  sscanf (val, \"%%d\", &n);\n";
9857              pr "  strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
9858              pr "  for (i = 0; i < n; ++i) {\n";
9859              pr "    strs[i*2] = safe_malloc (g, 16);\n";
9860              pr "    strs[i*2+1] = safe_malloc (g, 16);\n";
9861              pr "    snprintf (strs[i*2], 16, \"%%d\", i);\n";
9862              pr "    snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
9863              pr "  }\n";
9864              pr "  strs[n*2] = NULL;\n";
9865              pr "  return strs;\n"
9866          | RBufferOut _ ->
9867              pr "  return strdup (val);\n"
9868         );
9869         pr "}\n";
9870         pr "\n"
9871       ) else (
9872         pr "/* Test error return. */\n";
9873         generate_prototype ~extern:false ~semicolon:false ~newline:true
9874           ~handle:"g" ~prefix:"guestfs__" name style;
9875         pr "{\n";
9876         pr "  error (g, \"error\");\n";
9877         (match fst style with
9878          | RErr | RInt _ | RInt64 _ | RBool _ ->
9879              pr "  return -1;\n"
9880          | RConstString _ | RConstOptString _
9881          | RString _ | RStringList _ | RStruct _
9882          | RStructList _
9883          | RHashtable _
9884          | RBufferOut _ ->
9885              pr "  return NULL;\n"
9886         );
9887         pr "}\n";
9888         pr "\n"
9889       )
9890   ) tests
9891
9892 and generate_ocaml_bindtests () =
9893   generate_header OCamlStyle GPLv2;
9894
9895   pr "\
9896 let () =
9897   let g = Guestfs.create () in
9898 ";
9899
9900   let mkargs args =
9901     String.concat " " (
9902       List.map (
9903         function
9904         | CallString s -> "\"" ^ s ^ "\""
9905         | CallOptString None -> "None"
9906         | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
9907         | CallStringList xs ->
9908             "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
9909         | CallInt i when i >= 0 -> string_of_int i
9910         | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
9911         | CallInt64 i when i >= 0L -> Int64.to_string i ^ "L"
9912         | CallInt64 i (* when i < 0L *) -> "(" ^ Int64.to_string i ^ "L)"
9913         | CallBool b -> string_of_bool b
9914       ) args
9915     )
9916   in
9917
9918   generate_lang_bindtests (
9919     fun f args -> pr "  Guestfs.%s g %s;\n" f (mkargs args)
9920   );
9921
9922   pr "print_endline \"EOF\"\n"
9923
9924 and generate_perl_bindtests () =
9925   pr "#!/usr/bin/perl -w\n";
9926   generate_header HashStyle GPLv2;
9927
9928   pr "\
9929 use strict;
9930
9931 use Sys::Guestfs;
9932
9933 my $g = Sys::Guestfs->new ();
9934 ";
9935
9936   let mkargs args =
9937     String.concat ", " (
9938       List.map (
9939         function
9940         | CallString s -> "\"" ^ s ^ "\""
9941         | CallOptString None -> "undef"
9942         | CallOptString (Some s) -> sprintf "\"%s\"" s
9943         | CallStringList xs ->
9944             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
9945         | CallInt i -> string_of_int i
9946         | CallInt64 i -> Int64.to_string i
9947         | CallBool b -> if b then "1" else "0"
9948       ) args
9949     )
9950   in
9951
9952   generate_lang_bindtests (
9953     fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
9954   );
9955
9956   pr "print \"EOF\\n\"\n"
9957
9958 and generate_python_bindtests () =
9959   generate_header HashStyle GPLv2;
9960
9961   pr "\
9962 import guestfs
9963
9964 g = guestfs.GuestFS ()
9965 ";
9966
9967   let mkargs args =
9968     String.concat ", " (
9969       List.map (
9970         function
9971         | CallString s -> "\"" ^ s ^ "\""
9972         | CallOptString None -> "None"
9973         | CallOptString (Some s) -> sprintf "\"%s\"" s
9974         | CallStringList xs ->
9975             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
9976         | CallInt i -> string_of_int i
9977         | CallInt64 i -> Int64.to_string i
9978         | CallBool b -> if b then "1" else "0"
9979       ) args
9980     )
9981   in
9982
9983   generate_lang_bindtests (
9984     fun f args -> pr "g.%s (%s)\n" f (mkargs args)
9985   );
9986
9987   pr "print \"EOF\"\n"
9988
9989 and generate_ruby_bindtests () =
9990   generate_header HashStyle GPLv2;
9991
9992   pr "\
9993 require 'guestfs'
9994
9995 g = Guestfs::create()
9996 ";
9997
9998   let mkargs args =
9999     String.concat ", " (
10000       List.map (
10001         function
10002         | CallString s -> "\"" ^ s ^ "\""
10003         | CallOptString None -> "nil"
10004         | CallOptString (Some s) -> sprintf "\"%s\"" s
10005         | CallStringList xs ->
10006             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10007         | CallInt i -> string_of_int i
10008         | CallInt64 i -> Int64.to_string i
10009         | CallBool b -> string_of_bool b
10010       ) args
10011     )
10012   in
10013
10014   generate_lang_bindtests (
10015     fun f args -> pr "g.%s(%s)\n" f (mkargs args)
10016   );
10017
10018   pr "print \"EOF\\n\"\n"
10019
10020 and generate_java_bindtests () =
10021   generate_header CStyle GPLv2;
10022
10023   pr "\
10024 import com.redhat.et.libguestfs.*;
10025
10026 public class Bindtests {
10027     public static void main (String[] argv)
10028     {
10029         try {
10030             GuestFS g = new GuestFS ();
10031 ";
10032
10033   let mkargs args =
10034     String.concat ", " (
10035       List.map (
10036         function
10037         | CallString s -> "\"" ^ s ^ "\""
10038         | CallOptString None -> "null"
10039         | CallOptString (Some s) -> sprintf "\"%s\"" s
10040         | CallStringList xs ->
10041             "new String[]{" ^
10042               String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
10043         | CallInt i -> string_of_int i
10044         | CallInt64 i -> Int64.to_string i
10045         | CallBool b -> string_of_bool b
10046       ) args
10047     )
10048   in
10049
10050   generate_lang_bindtests (
10051     fun f args -> pr "            g.%s (%s);\n" f (mkargs args)
10052   );
10053
10054   pr "
10055             System.out.println (\"EOF\");
10056         }
10057         catch (Exception exn) {
10058             System.err.println (exn);
10059             System.exit (1);
10060         }
10061     }
10062 }
10063 "
10064
10065 and generate_haskell_bindtests () =
10066   generate_header HaskellStyle GPLv2;
10067
10068   pr "\
10069 module Bindtests where
10070 import qualified Guestfs
10071
10072 main = do
10073   g <- Guestfs.create
10074 ";
10075
10076   let mkargs args =
10077     String.concat " " (
10078       List.map (
10079         function
10080         | CallString s -> "\"" ^ s ^ "\""
10081         | CallOptString None -> "Nothing"
10082         | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
10083         | CallStringList xs ->
10084             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10085         | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
10086         | CallInt i -> string_of_int i
10087         | CallInt64 i when i < 0L -> "(" ^ Int64.to_string i ^ ")"
10088         | CallInt64 i -> Int64.to_string i
10089         | CallBool true -> "True"
10090         | CallBool false -> "False"
10091       ) args
10092     )
10093   in
10094
10095   generate_lang_bindtests (
10096     fun f args -> pr "  Guestfs.%s g %s\n" f (mkargs args)
10097   );
10098
10099   pr "  putStrLn \"EOF\"\n"
10100
10101 (* Language-independent bindings tests - we do it this way to
10102  * ensure there is parity in testing bindings across all languages.
10103  *)
10104 and generate_lang_bindtests call =
10105   call "test0" [CallString "abc"; CallOptString (Some "def");
10106                 CallStringList []; CallBool false;
10107                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10108   call "test0" [CallString "abc"; CallOptString None;
10109                 CallStringList []; CallBool false;
10110                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10111   call "test0" [CallString ""; CallOptString (Some "def");
10112                 CallStringList []; CallBool false;
10113                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10114   call "test0" [CallString ""; CallOptString (Some "");
10115                 CallStringList []; CallBool false;
10116                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10117   call "test0" [CallString "abc"; CallOptString (Some "def");
10118                 CallStringList ["1"]; CallBool false;
10119                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10120   call "test0" [CallString "abc"; CallOptString (Some "def");
10121                 CallStringList ["1"; "2"]; CallBool false;
10122                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10123   call "test0" [CallString "abc"; CallOptString (Some "def");
10124                 CallStringList ["1"]; CallBool true;
10125                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10126   call "test0" [CallString "abc"; CallOptString (Some "def");
10127                 CallStringList ["1"]; CallBool false;
10128                 CallInt (-1); CallInt64 (-1L); CallString "123"; CallString "456"];
10129   call "test0" [CallString "abc"; CallOptString (Some "def");
10130                 CallStringList ["1"]; CallBool false;
10131                 CallInt (-2); CallInt64 (-2L); CallString "123"; CallString "456"];
10132   call "test0" [CallString "abc"; CallOptString (Some "def");
10133                 CallStringList ["1"]; CallBool false;
10134                 CallInt 1; CallInt64 1L; CallString "123"; CallString "456"];
10135   call "test0" [CallString "abc"; CallOptString (Some "def");
10136                 CallStringList ["1"]; CallBool false;
10137                 CallInt 2; CallInt64 2L; CallString "123"; CallString "456"];
10138   call "test0" [CallString "abc"; CallOptString (Some "def");
10139                 CallStringList ["1"]; CallBool false;
10140                 CallInt 4095; CallInt64 4095L; CallString "123"; CallString "456"];
10141   call "test0" [CallString "abc"; CallOptString (Some "def");
10142                 CallStringList ["1"]; CallBool false;
10143                 CallInt 0; CallInt64 0L; CallString ""; CallString ""]
10144
10145 (* XXX Add here tests of the return and error functions. *)
10146
10147 (* This is used to generate the src/MAX_PROC_NR file which
10148  * contains the maximum procedure number, a surrogate for the
10149  * ABI version number.  See src/Makefile.am for the details.
10150  *)
10151 and generate_max_proc_nr () =
10152   let proc_nrs = List.map (
10153     fun (_, _, proc_nr, _, _, _, _) -> proc_nr
10154   ) daemon_functions in
10155
10156   let max_proc_nr = List.fold_left max 0 proc_nrs in
10157
10158   pr "%d\n" max_proc_nr
10159
10160 let output_to filename =
10161   let filename_new = filename ^ ".new" in
10162   chan := open_out filename_new;
10163   let close () =
10164     close_out !chan;
10165     chan := Pervasives.stdout;
10166
10167     (* Is the new file different from the current file? *)
10168     if Sys.file_exists filename && files_equal filename filename_new then
10169       unlink filename_new               (* same, so skip it *)
10170     else (
10171       (* different, overwrite old one *)
10172       (try chmod filename 0o644 with Unix_error _ -> ());
10173       rename filename_new filename;
10174       chmod filename 0o444;
10175       printf "written %s\n%!" filename;
10176     )
10177   in
10178   close
10179
10180 let perror msg = function
10181   | Unix_error (err, _, _) ->
10182       eprintf "%s: %s\n" msg (error_message err)
10183   | exn ->
10184       eprintf "%s: %s\n" msg (Printexc.to_string exn)
10185
10186 (* Main program. *)
10187 let () =
10188   let lock_fd =
10189     try openfile "HACKING" [O_RDWR] 0
10190     with
10191     | Unix_error (ENOENT, _, _) ->
10192         eprintf "\
10193 You are probably running this from the wrong directory.
10194 Run it from the top source directory using the command
10195   src/generator.ml
10196 ";
10197         exit 1
10198     | exn ->
10199         perror "open: HACKING" exn;
10200         exit 1 in
10201
10202   (* Acquire a lock so parallel builds won't try to run the generator
10203    * twice at the same time.  Subsequent builds will wait for the first
10204    * one to finish.  Note the lock is released implicitly when the
10205    * program exits.
10206    *)
10207   (try lockf lock_fd F_LOCK 1
10208    with exn ->
10209      perror "lock: HACKING" exn;
10210      exit 1);
10211
10212   check_functions ();
10213
10214   let close = output_to "src/guestfs_protocol.x" in
10215   generate_xdr ();
10216   close ();
10217
10218   let close = output_to "src/guestfs-structs.h" in
10219   generate_structs_h ();
10220   close ();
10221
10222   let close = output_to "src/guestfs-actions.h" in
10223   generate_actions_h ();
10224   close ();
10225
10226   let close = output_to "src/guestfs-internal-actions.h" in
10227   generate_internal_actions_h ();
10228   close ();
10229
10230   let close = output_to "src/guestfs-actions.c" in
10231   generate_client_actions ();
10232   close ();
10233
10234   let close = output_to "daemon/actions.h" in
10235   generate_daemon_actions_h ();
10236   close ();
10237
10238   let close = output_to "daemon/stubs.c" in
10239   generate_daemon_actions ();
10240   close ();
10241
10242   let close = output_to "daemon/names.c" in
10243   generate_daemon_names ();
10244   close ();
10245
10246   let close = output_to "capitests/tests.c" in
10247   generate_tests ();
10248   close ();
10249
10250   let close = output_to "src/guestfs-bindtests.c" in
10251   generate_bindtests ();
10252   close ();
10253
10254   let close = output_to "fish/cmds.c" in
10255   generate_fish_cmds ();
10256   close ();
10257
10258   let close = output_to "fish/completion.c" in
10259   generate_fish_completion ();
10260   close ();
10261
10262   let close = output_to "guestfs-structs.pod" in
10263   generate_structs_pod ();
10264   close ();
10265
10266   let close = output_to "guestfs-actions.pod" in
10267   generate_actions_pod ();
10268   close ();
10269
10270   let close = output_to "guestfish-actions.pod" in
10271   generate_fish_actions_pod ();
10272   close ();
10273
10274   let close = output_to "ocaml/guestfs.mli" in
10275   generate_ocaml_mli ();
10276   close ();
10277
10278   let close = output_to "ocaml/guestfs.ml" in
10279   generate_ocaml_ml ();
10280   close ();
10281
10282   let close = output_to "ocaml/guestfs_c_actions.c" in
10283   generate_ocaml_c ();
10284   close ();
10285
10286   let close = output_to "ocaml/bindtests.ml" in
10287   generate_ocaml_bindtests ();
10288   close ();
10289
10290   let close = output_to "perl/Guestfs.xs" in
10291   generate_perl_xs ();
10292   close ();
10293
10294   let close = output_to "perl/lib/Sys/Guestfs.pm" in
10295   generate_perl_pm ();
10296   close ();
10297
10298   let close = output_to "perl/bindtests.pl" in
10299   generate_perl_bindtests ();
10300   close ();
10301
10302   let close = output_to "python/guestfs-py.c" in
10303   generate_python_c ();
10304   close ();
10305
10306   let close = output_to "python/guestfs.py" in
10307   generate_python_py ();
10308   close ();
10309
10310   let close = output_to "python/bindtests.py" in
10311   generate_python_bindtests ();
10312   close ();
10313
10314   let close = output_to "ruby/ext/guestfs/_guestfs.c" in
10315   generate_ruby_c ();
10316   close ();
10317
10318   let close = output_to "ruby/bindtests.rb" in
10319   generate_ruby_bindtests ();
10320   close ();
10321
10322   let close = output_to "java/com/redhat/et/libguestfs/GuestFS.java" in
10323   generate_java_java ();
10324   close ();
10325
10326   List.iter (
10327     fun (typ, jtyp) ->
10328       let cols = cols_of_struct typ in
10329       let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
10330       let close = output_to filename in
10331       generate_java_struct jtyp cols;
10332       close ();
10333   ) java_structs;
10334
10335   let close = output_to "java/Makefile.inc" in
10336   generate_java_makefile_inc ();
10337   close ();
10338
10339   let close = output_to "java/com_redhat_et_libguestfs_GuestFS.c" in
10340   generate_java_c ();
10341   close ();
10342
10343   let close = output_to "java/Bindtests.java" in
10344   generate_java_bindtests ();
10345   close ();
10346
10347   let close = output_to "haskell/Guestfs.hs" in
10348   generate_haskell_hs ();
10349   close ();
10350
10351   let close = output_to "haskell/Bindtests.hs" in
10352   generate_haskell_bindtests ();
10353   close ();
10354
10355   let close = output_to "src/MAX_PROC_NR" in
10356   generate_max_proc_nr ();
10357   close ();
10358
10359   (* Always generate this file last, and unconditionally.  It's used
10360    * by the Makefile to know when we must re-run the generator.
10361    *)
10362   let chan = open_out "src/stamp-generator" in
10363   fprintf chan "1\n";
10364   close_out chan