1c533fae255772d09600d737132c82bb5a10f60d
[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   | Optional of string    (* function is part of an optional group *)
179
180 (* You can supply zero or as many tests as you want per API call.
181  *
182  * Note that the test environment has 3 block devices, of size 500MB,
183  * 50MB and 10MB (respectively /dev/sda, /dev/sdb, /dev/sdc), and
184  * a fourth ISO block device with some known files on it (/dev/sdd).
185  *
186  * Note for partitioning purposes, the 500MB device has 1015 cylinders.
187  * Number of cylinders was 63 for IDE emulated disks with precisely
188  * the same size.  How exactly this is calculated is a mystery.
189  *
190  * The ISO block device (/dev/sdd) comes from images/test.iso.
191  *
192  * To be able to run the tests in a reasonable amount of time,
193  * the virtual machine and block devices are reused between tests.
194  * So don't try testing kill_subprocess :-x
195  *
196  * Between each test we blockdev-setrw, umount-all, lvm-remove-all.
197  *
198  * Don't assume anything about the previous contents of the block
199  * devices.  Use 'Init*' to create some initial scenarios.
200  *
201  * You can add a prerequisite clause to any individual test.  This
202  * is a run-time check, which, if it fails, causes the test to be
203  * skipped.  Useful if testing a command which might not work on
204  * all variations of libguestfs builds.  A test that has prerequisite
205  * of 'Always' is run unconditionally.
206  *
207  * In addition, packagers can skip individual tests by setting the
208  * environment variables:     eg:
209  *   SKIP_TEST_<CMD>_<NUM>=1  SKIP_TEST_COMMAND_3=1  (skips test #3 of command)
210  *   SKIP_TEST_<CMD>=1        SKIP_TEST_ZEROFREE=1   (skips all zerofree tests)
211  *)
212 type tests = (test_init * test_prereq * test) list
213 and test =
214     (* Run the command sequence and just expect nothing to fail. *)
215   | TestRun of seq
216
217     (* Run the command sequence and expect the output of the final
218      * command to be the string.
219      *)
220   | TestOutput of seq * string
221
222     (* Run the command sequence and expect the output of the final
223      * command to be the list of strings.
224      *)
225   | TestOutputList of seq * string list
226
227     (* Run the command sequence and expect the output of the final
228      * command to be the list of block devices (could be either
229      * "/dev/sd.." or "/dev/hd.." form - we don't check the 5th
230      * character of each string).
231      *)
232   | TestOutputListOfDevices of seq * string list
233
234     (* Run the command sequence and expect the output of the final
235      * command to be the integer.
236      *)
237   | TestOutputInt of seq * int
238
239     (* Run the command sequence and expect the output of the final
240      * command to be <op> <int>, eg. ">=", "1".
241      *)
242   | TestOutputIntOp of seq * string * int
243
244     (* Run the command sequence and expect the output of the final
245      * command to be a true value (!= 0 or != NULL).
246      *)
247   | TestOutputTrue of seq
248
249     (* Run the command sequence and expect the output of the final
250      * command to be a false value (== 0 or == NULL, but not an error).
251      *)
252   | TestOutputFalse of seq
253
254     (* Run the command sequence and expect the output of the final
255      * command to be a list of the given length (but don't care about
256      * content).
257      *)
258   | TestOutputLength of seq * int
259
260     (* Run the command sequence and expect the output of the final
261      * command to be a buffer (RBufferOut), ie. string + size.
262      *)
263   | TestOutputBuffer of seq * string
264
265     (* Run the command sequence and expect the output of the final
266      * command to be a structure.
267      *)
268   | TestOutputStruct of seq * test_field_compare list
269
270     (* Run the command sequence and expect the final command (only)
271      * to fail.
272      *)
273   | TestLastFail of seq
274
275 and test_field_compare =
276   | CompareWithInt of string * int
277   | CompareWithIntOp of string * string * int
278   | CompareWithString of string * string
279   | CompareFieldsIntEq of string * string
280   | CompareFieldsStrEq of string * string
281
282 (* Test prerequisites. *)
283 and test_prereq =
284     (* Test always runs. *)
285   | Always
286
287     (* Test is currently disabled - eg. it fails, or it tests some
288      * unimplemented feature.
289      *)
290   | Disabled
291
292     (* 'string' is some C code (a function body) that should return
293      * true or false.  The test will run if the code returns true.
294      *)
295   | If of string
296
297     (* As for 'If' but the test runs _unless_ the code returns true. *)
298   | Unless of string
299
300 (* Some initial scenarios for testing. *)
301 and test_init =
302     (* Do nothing, block devices could contain random stuff including
303      * LVM PVs, and some filesystems might be mounted.  This is usually
304      * a bad idea.
305      *)
306   | InitNone
307
308     (* Block devices are empty and no filesystems are mounted. *)
309   | InitEmpty
310
311     (* /dev/sda contains a single partition /dev/sda1, with random
312      * content.  /dev/sdb and /dev/sdc may have random content.
313      * No LVM.
314      *)
315   | InitPartition
316
317     (* /dev/sda contains a single partition /dev/sda1, which is formatted
318      * as ext2, empty [except for lost+found] and mounted on /.
319      * /dev/sdb and /dev/sdc may have random content.
320      * No LVM.
321      *)
322   | InitBasicFS
323
324     (* /dev/sda:
325      *   /dev/sda1 (is a PV):
326      *     /dev/VG/LV (size 8MB):
327      *       formatted as ext2, empty [except for lost+found], mounted on /
328      * /dev/sdb and /dev/sdc may have random content.
329      *)
330   | InitBasicFSonLVM
331
332     (* /dev/sdd (the ISO, see images/ directory in source)
333      * is mounted on /
334      *)
335   | InitISOFS
336
337 (* Sequence of commands for testing. *)
338 and seq = cmd list
339 and cmd = string list
340
341 (* Note about long descriptions: When referring to another
342  * action, use the format C<guestfs_other> (ie. the full name of
343  * the C function).  This will be replaced as appropriate in other
344  * language bindings.
345  *
346  * Apart from that, long descriptions are just perldoc paragraphs.
347  *)
348
349 (* Generate a random UUID (used in tests). *)
350 let uuidgen () =
351   let chan = open_process_in "uuidgen" in
352   let uuid = input_line chan in
353   (match close_process_in chan with
354    | WEXITED 0 -> ()
355    | WEXITED _ ->
356        failwith "uuidgen: process exited with non-zero status"
357    | WSIGNALED _ | WSTOPPED _ ->
358        failwith "uuidgen: process signalled or stopped by signal"
359   );
360   uuid
361
362 (* These test functions are used in the language binding tests. *)
363
364 let test_all_args = [
365   String "str";
366   OptString "optstr";
367   StringList "strlist";
368   Bool "b";
369   Int "integer";
370   Int64 "integer64";
371   FileIn "filein";
372   FileOut "fileout";
373 ]
374
375 let test_all_rets = [
376   (* except for RErr, which is tested thoroughly elsewhere *)
377   "test0rint",         RInt "valout";
378   "test0rint64",       RInt64 "valout";
379   "test0rbool",        RBool "valout";
380   "test0rconststring", RConstString "valout";
381   "test0rconstoptstring", RConstOptString "valout";
382   "test0rstring",      RString "valout";
383   "test0rstringlist",  RStringList "valout";
384   "test0rstruct",      RStruct ("valout", "lvm_pv");
385   "test0rstructlist",  RStructList ("valout", "lvm_pv");
386   "test0rhashtable",   RHashtable "valout";
387 ]
388
389 let test_functions = [
390   ("test0", (RErr, test_all_args), -1, [NotInFish; NotInDocs],
391    [],
392    "internal test function - do not use",
393    "\
394 This is an internal test function which is used to test whether
395 the automatically generated bindings can handle every possible
396 parameter type correctly.
397
398 It echos the contents of each parameter to stdout.
399
400 You probably don't want to call this function.");
401 ] @ List.flatten (
402   List.map (
403     fun (name, ret) ->
404       [(name, (ret, [String "val"]), -1, [NotInFish; NotInDocs],
405         [],
406         "internal test function - do not use",
407         "\
408 This is an internal test function which is used to test whether
409 the automatically generated bindings can handle every possible
410 return type correctly.
411
412 It converts string C<val> to the return type.
413
414 You probably don't want to call this function.");
415        (name ^ "err", (ret, []), -1, [NotInFish; NotInDocs],
416         [],
417         "internal test function - do not use",
418         "\
419 This is an internal test function which is used to test whether
420 the automatically generated bindings can handle every possible
421 return type correctly.
422
423 This function always returns an error.
424
425 You probably don't want to call this function.")]
426   ) test_all_rets
427 )
428
429 (* non_daemon_functions are any functions which don't get processed
430  * in the daemon, eg. functions for setting and getting local
431  * configuration values.
432  *)
433
434 let non_daemon_functions = test_functions @ [
435   ("launch", (RErr, []), -1, [FishAlias "run"; FishAction "launch"],
436    [],
437    "launch the qemu subprocess",
438    "\
439 Internally libguestfs is implemented by running a virtual machine
440 using L<qemu(1)>.
441
442 You should call this after configuring the handle
443 (eg. adding drives) but before performing any actions.");
444
445   ("wait_ready", (RErr, []), -1, [NotInFish],
446    [],
447    "wait until the qemu subprocess launches (no op)",
448    "\
449 This function is a no op.
450
451 In versions of the API E<lt> 1.0.71 you had to call this function
452 just after calling C<guestfs_launch> to wait for the launch
453 to complete.  However this is no longer necessary because
454 C<guestfs_launch> now does the waiting.
455
456 If you see any calls to this function in code then you can just
457 remove them, unless you want to retain compatibility with older
458 versions of the API.");
459
460   ("kill_subprocess", (RErr, []), -1, [],
461    [],
462    "kill the qemu subprocess",
463    "\
464 This kills the qemu subprocess.  You should never need to call this.");
465
466   ("add_drive", (RErr, [String "filename"]), -1, [FishAlias "add"],
467    [],
468    "add an image to examine or modify",
469    "\
470 This function adds a virtual machine disk image C<filename> to the
471 guest.  The first time you call this function, the disk appears as IDE
472 disk 0 (C</dev/sda>) in the guest, the second time as C</dev/sdb>, and
473 so on.
474
475 You don't necessarily need to be root when using libguestfs.  However
476 you obviously do need sufficient permissions to access the filename
477 for whatever operations you want to perform (ie. read access if you
478 just want to read the image or write access if you want to modify the
479 image).
480
481 This is equivalent to the qemu parameter
482 C<-drive file=filename,cache=off,if=...>.
483 C<cache=off> is omitted in cases where it is not supported by
484 the underlying filesystem.
485
486 Note that this call checks for the existence of C<filename>.  This
487 stops you from specifying other types of drive which are supported
488 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
489 the general C<guestfs_config> call instead.");
490
491   ("add_cdrom", (RErr, [String "filename"]), -1, [FishAlias "cdrom"],
492    [],
493    "add a CD-ROM disk image to examine",
494    "\
495 This function adds a virtual CD-ROM disk image to the guest.
496
497 This is equivalent to the qemu parameter C<-cdrom filename>.
498
499 Note that this call checks for the existence of C<filename>.  This
500 stops you from specifying other types of drive which are supported
501 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
502 the general C<guestfs_config> call instead.");
503
504   ("add_drive_ro", (RErr, [String "filename"]), -1, [FishAlias "add-ro"],
505    [],
506    "add a drive in snapshot mode (read-only)",
507    "\
508 This adds a drive in snapshot mode, making it effectively
509 read-only.
510
511 Note that writes to the device are allowed, and will be seen for
512 the duration of the guestfs handle, but they are written
513 to a temporary file which is discarded as soon as the guestfs
514 handle is closed.  We don't currently have any method to enable
515 changes to be committed, although qemu can support this.
516
517 This is equivalent to the qemu parameter
518 C<-drive file=filename,snapshot=on,if=...>.
519
520 Note that this call checks for the existence of C<filename>.  This
521 stops you from specifying other types of drive which are supported
522 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
523 the general C<guestfs_config> call instead.");
524
525   ("config", (RErr, [String "qemuparam"; OptString "qemuvalue"]), -1, [],
526    [],
527    "add qemu parameters",
528    "\
529 This can be used to add arbitrary qemu command line parameters
530 of the form C<-param value>.  Actually it's not quite arbitrary - we
531 prevent you from setting some parameters which would interfere with
532 parameters that we use.
533
534 The first character of C<param> string must be a C<-> (dash).
535
536 C<value> can be NULL.");
537
538   ("set_qemu", (RErr, [String "qemu"]), -1, [FishAlias "qemu"],
539    [],
540    "set the qemu binary",
541    "\
542 Set the qemu binary that we will use.
543
544 The default is chosen when the library was compiled by the
545 configure script.
546
547 You can also override this by setting the C<LIBGUESTFS_QEMU>
548 environment variable.
549
550 Setting C<qemu> to C<NULL> restores the default qemu binary.");
551
552   ("get_qemu", (RConstString "qemu", []), -1, [],
553    [InitNone, Always, TestRun (
554       [["get_qemu"]])],
555    "get the qemu binary",
556    "\
557 Return the current qemu binary.
558
559 This is always non-NULL.  If it wasn't set already, then this will
560 return the default qemu binary name.");
561
562   ("set_path", (RErr, [String "searchpath"]), -1, [FishAlias "path"],
563    [],
564    "set the search path",
565    "\
566 Set the path that libguestfs searches for kernel and initrd.img.
567
568 The default is C<$libdir/guestfs> unless overridden by setting
569 C<LIBGUESTFS_PATH> environment variable.
570
571 Setting C<path> to C<NULL> restores the default path.");
572
573   ("get_path", (RConstString "path", []), -1, [],
574    [InitNone, Always, TestRun (
575       [["get_path"]])],
576    "get the search path",
577    "\
578 Return the current search path.
579
580 This is always non-NULL.  If it wasn't set already, then this will
581 return the default path.");
582
583   ("set_append", (RErr, [OptString "append"]), -1, [FishAlias "append"],
584    [],
585    "add options to kernel command line",
586    "\
587 This function is used to add additional options to the
588 guest kernel command line.
589
590 The default is C<NULL> unless overridden by setting
591 C<LIBGUESTFS_APPEND> environment variable.
592
593 Setting C<append> to C<NULL> means I<no> additional options
594 are passed (libguestfs always adds a few of its own).");
595
596   ("get_append", (RConstOptString "append", []), -1, [],
597    (* This cannot be tested with the current framework.  The
598     * function can return NULL in normal operations, which the
599     * test framework interprets as an error.
600     *)
601    [],
602    "get the additional kernel options",
603    "\
604 Return the additional kernel options which are added to the
605 guest kernel command line.
606
607 If C<NULL> then no options are added.");
608
609   ("set_autosync", (RErr, [Bool "autosync"]), -1, [FishAlias "autosync"],
610    [],
611    "set autosync mode",
612    "\
613 If C<autosync> is true, this enables autosync.  Libguestfs will make a
614 best effort attempt to run C<guestfs_umount_all> followed by
615 C<guestfs_sync> when the handle is closed
616 (also if the program exits without closing handles).
617
618 This is disabled by default (except in guestfish where it is
619 enabled by default).");
620
621   ("get_autosync", (RBool "autosync", []), -1, [],
622    [InitNone, Always, TestRun (
623       [["get_autosync"]])],
624    "get autosync mode",
625    "\
626 Get the autosync flag.");
627
628   ("set_verbose", (RErr, [Bool "verbose"]), -1, [FishAlias "verbose"],
629    [],
630    "set verbose mode",
631    "\
632 If C<verbose> is true, this turns on verbose messages (to C<stderr>).
633
634 Verbose messages are disabled unless the environment variable
635 C<LIBGUESTFS_DEBUG> is defined and set to C<1>.");
636
637   ("get_verbose", (RBool "verbose", []), -1, [],
638    [],
639    "get verbose mode",
640    "\
641 This returns the verbose messages flag.");
642
643   ("is_ready", (RBool "ready", []), -1, [],
644    [InitNone, Always, TestOutputTrue (
645       [["is_ready"]])],
646    "is ready to accept commands",
647    "\
648 This returns true iff this handle is ready to accept commands
649 (in the C<READY> state).
650
651 For more information on states, see L<guestfs(3)>.");
652
653   ("is_config", (RBool "config", []), -1, [],
654    [InitNone, Always, TestOutputFalse (
655       [["is_config"]])],
656    "is in configuration state",
657    "\
658 This returns true iff this handle is being configured
659 (in the C<CONFIG> state).
660
661 For more information on states, see L<guestfs(3)>.");
662
663   ("is_launching", (RBool "launching", []), -1, [],
664    [InitNone, Always, TestOutputFalse (
665       [["is_launching"]])],
666    "is launching subprocess",
667    "\
668 This returns true iff this handle is launching the subprocess
669 (in the C<LAUNCHING> state).
670
671 For more information on states, see L<guestfs(3)>.");
672
673   ("is_busy", (RBool "busy", []), -1, [],
674    [InitNone, Always, TestOutputFalse (
675       [["is_busy"]])],
676    "is busy processing a command",
677    "\
678 This returns true iff this handle is busy processing a command
679 (in the C<BUSY> state).
680
681 For more information on states, see L<guestfs(3)>.");
682
683   ("get_state", (RInt "state", []), -1, [],
684    [],
685    "get the current state",
686    "\
687 This returns the current state as an opaque integer.  This is
688 only useful for printing debug and internal error messages.
689
690 For more information on states, see L<guestfs(3)>.");
691
692   ("set_memsize", (RErr, [Int "memsize"]), -1, [FishAlias "memsize"],
693    [InitNone, Always, TestOutputInt (
694       [["set_memsize"; "500"];
695        ["get_memsize"]], 500)],
696    "set memory allocated to the qemu subprocess",
697    "\
698 This sets the memory size in megabytes allocated to the
699 qemu subprocess.  This only has any effect if called before
700 C<guestfs_launch>.
701
702 You can also change this by setting the environment
703 variable C<LIBGUESTFS_MEMSIZE> before the handle is
704 created.
705
706 For more information on the architecture of libguestfs,
707 see L<guestfs(3)>.");
708
709   ("get_memsize", (RInt "memsize", []), -1, [],
710    [InitNone, Always, TestOutputIntOp (
711       [["get_memsize"]], ">=", 256)],
712    "get memory allocated to the qemu subprocess",
713    "\
714 This gets the memory size in megabytes allocated to the
715 qemu subprocess.
716
717 If C<guestfs_set_memsize> was not called
718 on this handle, and if C<LIBGUESTFS_MEMSIZE> was not set,
719 then this returns the compiled-in default value for memsize.
720
721 For more information on the architecture of libguestfs,
722 see L<guestfs(3)>.");
723
724   ("get_pid", (RInt "pid", []), -1, [FishAlias "pid"],
725    [InitNone, Always, TestOutputIntOp (
726       [["get_pid"]], ">=", 1)],
727    "get PID of qemu subprocess",
728    "\
729 Return the process ID of the qemu subprocess.  If there is no
730 qemu subprocess, then this will return an error.
731
732 This is an internal call used for debugging and testing.");
733
734   ("version", (RStruct ("version", "version"), []), -1, [],
735    [InitNone, Always, TestOutputStruct (
736       [["version"]], [CompareWithInt ("major", 1)])],
737    "get the library version number",
738    "\
739 Return the libguestfs version number that the program is linked
740 against.
741
742 Note that because of dynamic linking this is not necessarily
743 the version of libguestfs that you compiled against.  You can
744 compile the program, and then at runtime dynamically link
745 against a completely different C<libguestfs.so> library.
746
747 This call was added in version C<1.0.58>.  In previous
748 versions of libguestfs there was no way to get the version
749 number.  From C code you can use ELF weak linking tricks to find out if
750 this symbol exists (if it doesn't, then it's an earlier version).
751
752 The call returns a structure with four elements.  The first
753 three (C<major>, C<minor> and C<release>) are numbers and
754 correspond to the usual version triplet.  The fourth element
755 (C<extra>) is a string and is normally empty, but may be
756 used for distro-specific information.
757
758 To construct the original version string:
759 C<$major.$minor.$release$extra>
760
761 I<Note:> Don't use this call to test for availability
762 of features.  Distro backports makes this unreliable.  Use
763 C<guestfs_available> instead.");
764
765   ("set_selinux", (RErr, [Bool "selinux"]), -1, [FishAlias "selinux"],
766    [InitNone, Always, TestOutputTrue (
767       [["set_selinux"; "true"];
768        ["get_selinux"]])],
769    "set SELinux enabled or disabled at appliance boot",
770    "\
771 This sets the selinux flag that is passed to the appliance
772 at boot time.  The default is C<selinux=0> (disabled).
773
774 Note that if SELinux is enabled, it is always in
775 Permissive mode (C<enforcing=0>).
776
777 For more information on the architecture of libguestfs,
778 see L<guestfs(3)>.");
779
780   ("get_selinux", (RBool "selinux", []), -1, [],
781    [],
782    "get SELinux enabled flag",
783    "\
784 This returns the current setting of the selinux flag which
785 is passed to the appliance at boot time.  See C<guestfs_set_selinux>.
786
787 For more information on the architecture of libguestfs,
788 see L<guestfs(3)>.");
789
790   ("set_trace", (RErr, [Bool "trace"]), -1, [FishAlias "trace"],
791    [InitNone, Always, TestOutputFalse (
792       [["set_trace"; "false"];
793        ["get_trace"]])],
794    "enable or disable command traces",
795    "\
796 If the command trace flag is set to 1, then commands are
797 printed on stdout before they are executed in a format
798 which is very similar to the one used by guestfish.  In
799 other words, you can run a program with this enabled, and
800 you will get out a script which you can feed to guestfish
801 to perform the same set of actions.
802
803 If you want to trace C API calls into libguestfs (and
804 other libraries) then possibly a better way is to use
805 the external ltrace(1) command.
806
807 Command traces are disabled unless the environment variable
808 C<LIBGUESTFS_TRACE> is defined and set to C<1>.");
809
810   ("get_trace", (RBool "trace", []), -1, [],
811    [],
812    "get command trace enabled flag",
813    "\
814 Return the command trace flag.");
815
816   ("set_direct", (RErr, [Bool "direct"]), -1, [FishAlias "direct"],
817    [InitNone, Always, TestOutputFalse (
818       [["set_direct"; "false"];
819        ["get_direct"]])],
820    "enable or disable direct appliance mode",
821    "\
822 If the direct appliance mode flag is enabled, then stdin and
823 stdout are passed directly through to the appliance once it
824 is launched.
825
826 One consequence of this is that log messages aren't caught
827 by the library and handled by C<guestfs_set_log_message_callback>,
828 but go straight to stdout.
829
830 You probably don't want to use this unless you know what you
831 are doing.
832
833 The default is disabled.");
834
835   ("get_direct", (RBool "direct", []), -1, [],
836    [],
837    "get direct appliance mode flag",
838    "\
839 Return the direct appliance mode flag.");
840
841   ("set_recovery_proc", (RErr, [Bool "recoveryproc"]), -1, [FishAlias "recovery-proc"],
842    [InitNone, Always, TestOutputTrue (
843       [["set_recovery_proc"; "true"];
844        ["get_recovery_proc"]])],
845    "enable or disable the recovery process",
846    "\
847 If this is called with the parameter C<false> then
848 C<guestfs_launch> does not create a recovery process.  The
849 purpose of the recovery process is to stop runaway qemu
850 processes in the case where the main program aborts abruptly.
851
852 This only has any effect if called before C<guestfs_launch>,
853 and the default is true.
854
855 About the only time when you would want to disable this is
856 if the main process will fork itself into the background
857 (\"daemonize\" itself).  In this case the recovery process
858 thinks that the main program has disappeared and so kills
859 qemu, which is not very helpful.");
860
861   ("get_recovery_proc", (RBool "recoveryproc", []), -1, [],
862    [],
863    "get recovery process enabled flag",
864    "\
865 Return the recovery process enabled flag.");
866
867 ]
868
869 (* daemon_functions are any functions which cause some action
870  * to take place in the daemon.
871  *)
872
873 let daemon_functions = [
874   ("mount", (RErr, [Device "device"; String "mountpoint"]), 1, [],
875    [InitEmpty, Always, TestOutput (
876       [["part_disk"; "/dev/sda"; "mbr"];
877        ["mkfs"; "ext2"; "/dev/sda1"];
878        ["mount"; "/dev/sda1"; "/"];
879        ["write_file"; "/new"; "new file contents"; "0"];
880        ["cat"; "/new"]], "new file contents")],
881    "mount a guest disk at a position in the filesystem",
882    "\
883 Mount a guest disk at a position in the filesystem.  Block devices
884 are named C</dev/sda>, C</dev/sdb> and so on, as they were added to
885 the guest.  If those block devices contain partitions, they will have
886 the usual names (eg. C</dev/sda1>).  Also LVM C</dev/VG/LV>-style
887 names can be used.
888
889 The rules are the same as for L<mount(2)>:  A filesystem must
890 first be mounted on C</> before others can be mounted.  Other
891 filesystems can only be mounted on directories which already
892 exist.
893
894 The mounted filesystem is writable, if we have sufficient permissions
895 on the underlying device.
896
897 The filesystem options C<sync> and C<noatime> are set with this
898 call, in order to improve reliability.");
899
900   ("sync", (RErr, []), 2, [],
901    [ InitEmpty, Always, TestRun [["sync"]]],
902    "sync disks, writes are flushed through to the disk image",
903    "\
904 This syncs the disk, so that any writes are flushed through to the
905 underlying disk image.
906
907 You should always call this if you have modified a disk image, before
908 closing the handle.");
909
910   ("touch", (RErr, [Pathname "path"]), 3, [],
911    [InitBasicFS, Always, TestOutputTrue (
912       [["touch"; "/new"];
913        ["exists"; "/new"]])],
914    "update file timestamps or create a new file",
915    "\
916 Touch acts like the L<touch(1)> command.  It can be used to
917 update the timestamps on a file, or, if the file does not exist,
918 to create a new zero-length file.");
919
920   ("cat", (RString "content", [Pathname "path"]), 4, [ProtocolLimitWarning],
921    [InitISOFS, Always, TestOutput (
922       [["cat"; "/known-2"]], "abcdef\n")],
923    "list the contents of a file",
924    "\
925 Return the contents of the file named C<path>.
926
927 Note that this function cannot correctly handle binary files
928 (specifically, files containing C<\\0> character which is treated
929 as end of string).  For those you need to use the C<guestfs_read_file>
930 or C<guestfs_download> functions which have a more complex interface.");
931
932   ("ll", (RString "listing", [Pathname "directory"]), 5, [],
933    [], (* XXX Tricky to test because it depends on the exact format
934         * of the 'ls -l' command, which changes between F10 and F11.
935         *)
936    "list the files in a directory (long format)",
937    "\
938 List the files in C<directory> (relative to the root directory,
939 there is no cwd) in the format of 'ls -la'.
940
941 This command is mostly useful for interactive sessions.  It
942 is I<not> intended that you try to parse the output string.");
943
944   ("ls", (RStringList "listing", [Pathname "directory"]), 6, [],
945    [InitBasicFS, Always, TestOutputList (
946       [["touch"; "/new"];
947        ["touch"; "/newer"];
948        ["touch"; "/newest"];
949        ["ls"; "/"]], ["lost+found"; "new"; "newer"; "newest"])],
950    "list the files in a directory",
951    "\
952 List the files in C<directory> (relative to the root directory,
953 there is no cwd).  The '.' and '..' entries are not returned, but
954 hidden files are shown.
955
956 This command is mostly useful for interactive sessions.  Programs
957 should probably use C<guestfs_readdir> instead.");
958
959   ("list_devices", (RStringList "devices", []), 7, [],
960    [InitEmpty, Always, TestOutputListOfDevices (
961       [["list_devices"]], ["/dev/sda"; "/dev/sdb"; "/dev/sdc"; "/dev/sdd"])],
962    "list the block devices",
963    "\
964 List all the block devices.
965
966 The full block device names are returned, eg. C</dev/sda>");
967
968   ("list_partitions", (RStringList "partitions", []), 8, [],
969    [InitBasicFS, Always, TestOutputListOfDevices (
970       [["list_partitions"]], ["/dev/sda1"]);
971     InitEmpty, Always, TestOutputListOfDevices (
972       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
973        ["list_partitions"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
974    "list the partitions",
975    "\
976 List all the partitions detected on all block devices.
977
978 The full partition device names are returned, eg. C</dev/sda1>
979
980 This does not return logical volumes.  For that you will need to
981 call C<guestfs_lvs>.");
982
983   ("pvs", (RStringList "physvols", []), 9, [Optional "lvm2"],
984    [InitBasicFSonLVM, Always, TestOutputListOfDevices (
985       [["pvs"]], ["/dev/sda1"]);
986     InitEmpty, Always, TestOutputListOfDevices (
987       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
988        ["pvcreate"; "/dev/sda1"];
989        ["pvcreate"; "/dev/sda2"];
990        ["pvcreate"; "/dev/sda3"];
991        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
992    "list the LVM physical volumes (PVs)",
993    "\
994 List all the physical volumes detected.  This is the equivalent
995 of the L<pvs(8)> command.
996
997 This returns a list of just the device names that contain
998 PVs (eg. C</dev/sda2>).
999
1000 See also C<guestfs_pvs_full>.");
1001
1002   ("vgs", (RStringList "volgroups", []), 10, [Optional "lvm2"],
1003    [InitBasicFSonLVM, Always, TestOutputList (
1004       [["vgs"]], ["VG"]);
1005     InitEmpty, Always, TestOutputList (
1006       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1007        ["pvcreate"; "/dev/sda1"];
1008        ["pvcreate"; "/dev/sda2"];
1009        ["pvcreate"; "/dev/sda3"];
1010        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1011        ["vgcreate"; "VG2"; "/dev/sda3"];
1012        ["vgs"]], ["VG1"; "VG2"])],
1013    "list the LVM volume groups (VGs)",
1014    "\
1015 List all the volumes groups detected.  This is the equivalent
1016 of the L<vgs(8)> command.
1017
1018 This returns a list of just the volume group names that were
1019 detected (eg. C<VolGroup00>).
1020
1021 See also C<guestfs_vgs_full>.");
1022
1023   ("lvs", (RStringList "logvols", []), 11, [Optional "lvm2"],
1024    [InitBasicFSonLVM, Always, TestOutputList (
1025       [["lvs"]], ["/dev/VG/LV"]);
1026     InitEmpty, Always, TestOutputList (
1027       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1028        ["pvcreate"; "/dev/sda1"];
1029        ["pvcreate"; "/dev/sda2"];
1030        ["pvcreate"; "/dev/sda3"];
1031        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1032        ["vgcreate"; "VG2"; "/dev/sda3"];
1033        ["lvcreate"; "LV1"; "VG1"; "50"];
1034        ["lvcreate"; "LV2"; "VG1"; "50"];
1035        ["lvcreate"; "LV3"; "VG2"; "50"];
1036        ["lvs"]], ["/dev/VG1/LV1"; "/dev/VG1/LV2"; "/dev/VG2/LV3"])],
1037    "list the LVM logical volumes (LVs)",
1038    "\
1039 List all the logical volumes detected.  This is the equivalent
1040 of the L<lvs(8)> command.
1041
1042 This returns a list of the logical volume device names
1043 (eg. C</dev/VolGroup00/LogVol00>).
1044
1045 See also C<guestfs_lvs_full>.");
1046
1047   ("pvs_full", (RStructList ("physvols", "lvm_pv"), []), 12, [Optional "lvm2"],
1048    [], (* XXX how to test? *)
1049    "list the LVM physical volumes (PVs)",
1050    "\
1051 List all the physical volumes detected.  This is the equivalent
1052 of the L<pvs(8)> command.  The \"full\" version includes all fields.");
1053
1054   ("vgs_full", (RStructList ("volgroups", "lvm_vg"), []), 13, [Optional "lvm2"],
1055    [], (* XXX how to test? *)
1056    "list the LVM volume groups (VGs)",
1057    "\
1058 List all the volumes groups detected.  This is the equivalent
1059 of the L<vgs(8)> command.  The \"full\" version includes all fields.");
1060
1061   ("lvs_full", (RStructList ("logvols", "lvm_lv"), []), 14, [Optional "lvm2"],
1062    [], (* XXX how to test? *)
1063    "list the LVM logical volumes (LVs)",
1064    "\
1065 List all the logical volumes detected.  This is the equivalent
1066 of the L<lvs(8)> command.  The \"full\" version includes all fields.");
1067
1068   ("read_lines", (RStringList "lines", [Pathname "path"]), 15, [],
1069    [InitISOFS, Always, TestOutputList (
1070       [["read_lines"; "/known-4"]], ["abc"; "def"; "ghi"]);
1071     InitISOFS, Always, TestOutputList (
1072       [["read_lines"; "/empty"]], [])],
1073    "read file as lines",
1074    "\
1075 Return the contents of the file named C<path>.
1076
1077 The file contents are returned as a list of lines.  Trailing
1078 C<LF> and C<CRLF> character sequences are I<not> returned.
1079
1080 Note that this function cannot correctly handle binary files
1081 (specifically, files containing C<\\0> character which is treated
1082 as end of line).  For those you need to use the C<guestfs_read_file>
1083 function which has a more complex interface.");
1084
1085   ("aug_init", (RErr, [Pathname "root"; Int "flags"]), 16, [Optional "augeas"],
1086    [], (* XXX Augeas code needs tests. *)
1087    "create a new Augeas handle",
1088    "\
1089 Create a new Augeas handle for editing configuration files.
1090 If there was any previous Augeas handle associated with this
1091 guestfs session, then it is closed.
1092
1093 You must call this before using any other C<guestfs_aug_*>
1094 commands.
1095
1096 C<root> is the filesystem root.  C<root> must not be NULL,
1097 use C</> instead.
1098
1099 The flags are the same as the flags defined in
1100 E<lt>augeas.hE<gt>, the logical I<or> of the following
1101 integers:
1102
1103 =over 4
1104
1105 =item C<AUG_SAVE_BACKUP> = 1
1106
1107 Keep the original file with a C<.augsave> extension.
1108
1109 =item C<AUG_SAVE_NEWFILE> = 2
1110
1111 Save changes into a file with extension C<.augnew>, and
1112 do not overwrite original.  Overrides C<AUG_SAVE_BACKUP>.
1113
1114 =item C<AUG_TYPE_CHECK> = 4
1115
1116 Typecheck lenses (can be expensive).
1117
1118 =item C<AUG_NO_STDINC> = 8
1119
1120 Do not use standard load path for modules.
1121
1122 =item C<AUG_SAVE_NOOP> = 16
1123
1124 Make save a no-op, just record what would have been changed.
1125
1126 =item C<AUG_NO_LOAD> = 32
1127
1128 Do not load the tree in C<guestfs_aug_init>.
1129
1130 =back
1131
1132 To close the handle, you can call C<guestfs_aug_close>.
1133
1134 To find out more about Augeas, see L<http://augeas.net/>.");
1135
1136   ("aug_close", (RErr, []), 26, [Optional "augeas"],
1137    [], (* XXX Augeas code needs tests. *)
1138    "close the current Augeas handle",
1139    "\
1140 Close the current Augeas handle and free up any resources
1141 used by it.  After calling this, you have to call
1142 C<guestfs_aug_init> again before you can use any other
1143 Augeas functions.");
1144
1145   ("aug_defvar", (RInt "nrnodes", [String "name"; OptString "expr"]), 17, [Optional "augeas"],
1146    [], (* XXX Augeas code needs tests. *)
1147    "define an Augeas variable",
1148    "\
1149 Defines an Augeas variable C<name> whose value is the result
1150 of evaluating C<expr>.  If C<expr> is NULL, then C<name> is
1151 undefined.
1152
1153 On success this returns the number of nodes in C<expr>, or
1154 C<0> if C<expr> evaluates to something which is not a nodeset.");
1155
1156   ("aug_defnode", (RStruct ("nrnodescreated", "int_bool"), [String "name"; String "expr"; String "val"]), 18, [Optional "augeas"],
1157    [], (* XXX Augeas code needs tests. *)
1158    "define an Augeas node",
1159    "\
1160 Defines a variable C<name> whose value is the result of
1161 evaluating C<expr>.
1162
1163 If C<expr> evaluates to an empty nodeset, a node is created,
1164 equivalent to calling C<guestfs_aug_set> C<expr>, C<value>.
1165 C<name> will be the nodeset containing that single node.
1166
1167 On success this returns a pair containing the
1168 number of nodes in the nodeset, and a boolean flag
1169 if a node was created.");
1170
1171   ("aug_get", (RString "val", [String "augpath"]), 19, [Optional "augeas"],
1172    [], (* XXX Augeas code needs tests. *)
1173    "look up the value of an Augeas path",
1174    "\
1175 Look up the value associated with C<path>.  If C<path>
1176 matches exactly one node, the C<value> is returned.");
1177
1178   ("aug_set", (RErr, [String "augpath"; String "val"]), 20, [Optional "augeas"],
1179    [], (* XXX Augeas code needs tests. *)
1180    "set Augeas path to value",
1181    "\
1182 Set the value associated with C<path> to C<value>.");
1183
1184   ("aug_insert", (RErr, [String "augpath"; String "label"; Bool "before"]), 21, [Optional "augeas"],
1185    [], (* XXX Augeas code needs tests. *)
1186    "insert a sibling Augeas node",
1187    "\
1188 Create a new sibling C<label> for C<path>, inserting it into
1189 the tree before or after C<path> (depending on the boolean
1190 flag C<before>).
1191
1192 C<path> must match exactly one existing node in the tree, and
1193 C<label> must be a label, ie. not contain C</>, C<*> or end
1194 with a bracketed index C<[N]>.");
1195
1196   ("aug_rm", (RInt "nrnodes", [String "augpath"]), 22, [Optional "augeas"],
1197    [], (* XXX Augeas code needs tests. *)
1198    "remove an Augeas path",
1199    "\
1200 Remove C<path> and all of its children.
1201
1202 On success this returns the number of entries which were removed.");
1203
1204   ("aug_mv", (RErr, [String "src"; String "dest"]), 23, [Optional "augeas"],
1205    [], (* XXX Augeas code needs tests. *)
1206    "move Augeas node",
1207    "\
1208 Move the node C<src> to C<dest>.  C<src> must match exactly
1209 one node.  C<dest> is overwritten if it exists.");
1210
1211   ("aug_match", (RStringList "matches", [String "augpath"]), 24, [Optional "augeas"],
1212    [], (* XXX Augeas code needs tests. *)
1213    "return Augeas nodes which match augpath",
1214    "\
1215 Returns a list of paths which match the path expression C<path>.
1216 The returned paths are sufficiently qualified so that they match
1217 exactly one node in the current tree.");
1218
1219   ("aug_save", (RErr, []), 25, [Optional "augeas"],
1220    [], (* XXX Augeas code needs tests. *)
1221    "write all pending Augeas changes to disk",
1222    "\
1223 This writes all pending changes to disk.
1224
1225 The flags which were passed to C<guestfs_aug_init> affect exactly
1226 how files are saved.");
1227
1228   ("aug_load", (RErr, []), 27, [Optional "augeas"],
1229    [], (* XXX Augeas code needs tests. *)
1230    "load files into the tree",
1231    "\
1232 Load files into the tree.
1233
1234 See C<aug_load> in the Augeas documentation for the full gory
1235 details.");
1236
1237   ("aug_ls", (RStringList "matches", [String "augpath"]), 28, [Optional "augeas"],
1238    [], (* XXX Augeas code needs tests. *)
1239    "list Augeas nodes under augpath",
1240    "\
1241 This is just a shortcut for listing C<guestfs_aug_match>
1242 C<path/*> and sorting the resulting nodes into alphabetical order.");
1243
1244   ("rm", (RErr, [Pathname "path"]), 29, [],
1245    [InitBasicFS, Always, TestRun
1246       [["touch"; "/new"];
1247        ["rm"; "/new"]];
1248     InitBasicFS, Always, TestLastFail
1249       [["rm"; "/new"]];
1250     InitBasicFS, Always, TestLastFail
1251       [["mkdir"; "/new"];
1252        ["rm"; "/new"]]],
1253    "remove a file",
1254    "\
1255 Remove the single file C<path>.");
1256
1257   ("rmdir", (RErr, [Pathname "path"]), 30, [],
1258    [InitBasicFS, Always, TestRun
1259       [["mkdir"; "/new"];
1260        ["rmdir"; "/new"]];
1261     InitBasicFS, Always, TestLastFail
1262       [["rmdir"; "/new"]];
1263     InitBasicFS, Always, TestLastFail
1264       [["touch"; "/new"];
1265        ["rmdir"; "/new"]]],
1266    "remove a directory",
1267    "\
1268 Remove the single directory C<path>.");
1269
1270   ("rm_rf", (RErr, [Pathname "path"]), 31, [],
1271    [InitBasicFS, Always, TestOutputFalse
1272       [["mkdir"; "/new"];
1273        ["mkdir"; "/new/foo"];
1274        ["touch"; "/new/foo/bar"];
1275        ["rm_rf"; "/new"];
1276        ["exists"; "/new"]]],
1277    "remove a file or directory recursively",
1278    "\
1279 Remove the file or directory C<path>, recursively removing the
1280 contents if its a directory.  This is like the C<rm -rf> shell
1281 command.");
1282
1283   ("mkdir", (RErr, [Pathname "path"]), 32, [],
1284    [InitBasicFS, Always, TestOutputTrue
1285       [["mkdir"; "/new"];
1286        ["is_dir"; "/new"]];
1287     InitBasicFS, Always, TestLastFail
1288       [["mkdir"; "/new/foo/bar"]]],
1289    "create a directory",
1290    "\
1291 Create a directory named C<path>.");
1292
1293   ("mkdir_p", (RErr, [Pathname "path"]), 33, [],
1294    [InitBasicFS, Always, TestOutputTrue
1295       [["mkdir_p"; "/new/foo/bar"];
1296        ["is_dir"; "/new/foo/bar"]];
1297     InitBasicFS, Always, TestOutputTrue
1298       [["mkdir_p"; "/new/foo/bar"];
1299        ["is_dir"; "/new/foo"]];
1300     InitBasicFS, Always, TestOutputTrue
1301       [["mkdir_p"; "/new/foo/bar"];
1302        ["is_dir"; "/new"]];
1303     (* Regression tests for RHBZ#503133: *)
1304     InitBasicFS, Always, TestRun
1305       [["mkdir"; "/new"];
1306        ["mkdir_p"; "/new"]];
1307     InitBasicFS, Always, TestLastFail
1308       [["touch"; "/new"];
1309        ["mkdir_p"; "/new"]]],
1310    "create a directory and parents",
1311    "\
1312 Create a directory named C<path>, creating any parent directories
1313 as necessary.  This is like the C<mkdir -p> shell command.");
1314
1315   ("chmod", (RErr, [Int "mode"; Pathname "path"]), 34, [],
1316    [], (* XXX Need stat command to test *)
1317    "change file mode",
1318    "\
1319 Change the mode (permissions) of C<path> to C<mode>.  Only
1320 numeric modes are supported.");
1321
1322   ("chown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 35, [],
1323    [], (* XXX Need stat command to test *)
1324    "change file owner and group",
1325    "\
1326 Change the file owner to C<owner> and group to C<group>.
1327
1328 Only numeric uid and gid are supported.  If you want to use
1329 names, you will need to locate and parse the password file
1330 yourself (Augeas support makes this relatively easy).");
1331
1332   ("exists", (RBool "existsflag", [Pathname "path"]), 36, [],
1333    [InitISOFS, Always, TestOutputTrue (
1334       [["exists"; "/empty"]]);
1335     InitISOFS, Always, TestOutputTrue (
1336       [["exists"; "/directory"]])],
1337    "test if file or directory exists",
1338    "\
1339 This returns C<true> if and only if there is a file, directory
1340 (or anything) with the given C<path> name.
1341
1342 See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>.");
1343
1344   ("is_file", (RBool "fileflag", [Pathname "path"]), 37, [],
1345    [InitISOFS, Always, TestOutputTrue (
1346       [["is_file"; "/known-1"]]);
1347     InitISOFS, Always, TestOutputFalse (
1348       [["is_file"; "/directory"]])],
1349    "test if file exists",
1350    "\
1351 This returns C<true> if and only if there is a file
1352 with the given C<path> name.  Note that it returns false for
1353 other objects like directories.
1354
1355 See also C<guestfs_stat>.");
1356
1357   ("is_dir", (RBool "dirflag", [Pathname "path"]), 38, [],
1358    [InitISOFS, Always, TestOutputFalse (
1359       [["is_dir"; "/known-3"]]);
1360     InitISOFS, Always, TestOutputTrue (
1361       [["is_dir"; "/directory"]])],
1362    "test if file exists",
1363    "\
1364 This returns C<true> if and only if there is a directory
1365 with the given C<path> name.  Note that it returns false for
1366 other objects like files.
1367
1368 See also C<guestfs_stat>.");
1369
1370   ("pvcreate", (RErr, [Device "device"]), 39, [Optional "lvm2"],
1371    [InitEmpty, Always, TestOutputListOfDevices (
1372       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1373        ["pvcreate"; "/dev/sda1"];
1374        ["pvcreate"; "/dev/sda2"];
1375        ["pvcreate"; "/dev/sda3"];
1376        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1377    "create an LVM physical volume",
1378    "\
1379 This creates an LVM physical volume on the named C<device>,
1380 where C<device> should usually be a partition name such
1381 as C</dev/sda1>.");
1382
1383   ("vgcreate", (RErr, [String "volgroup"; DeviceList "physvols"]), 40, [Optional "lvm2"],
1384    [InitEmpty, Always, TestOutputList (
1385       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1386        ["pvcreate"; "/dev/sda1"];
1387        ["pvcreate"; "/dev/sda2"];
1388        ["pvcreate"; "/dev/sda3"];
1389        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1390        ["vgcreate"; "VG2"; "/dev/sda3"];
1391        ["vgs"]], ["VG1"; "VG2"])],
1392    "create an LVM volume group",
1393    "\
1394 This creates an LVM volume group called C<volgroup>
1395 from the non-empty list of physical volumes C<physvols>.");
1396
1397   ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [Optional "lvm2"],
1398    [InitEmpty, Always, TestOutputList (
1399       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1400        ["pvcreate"; "/dev/sda1"];
1401        ["pvcreate"; "/dev/sda2"];
1402        ["pvcreate"; "/dev/sda3"];
1403        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1404        ["vgcreate"; "VG2"; "/dev/sda3"];
1405        ["lvcreate"; "LV1"; "VG1"; "50"];
1406        ["lvcreate"; "LV2"; "VG1"; "50"];
1407        ["lvcreate"; "LV3"; "VG2"; "50"];
1408        ["lvcreate"; "LV4"; "VG2"; "50"];
1409        ["lvcreate"; "LV5"; "VG2"; "50"];
1410        ["lvs"]],
1411       ["/dev/VG1/LV1"; "/dev/VG1/LV2";
1412        "/dev/VG2/LV3"; "/dev/VG2/LV4"; "/dev/VG2/LV5"])],
1413    "create an LVM volume group",
1414    "\
1415 This creates an LVM volume group called C<logvol>
1416 on the volume group C<volgroup>, with C<size> megabytes.");
1417
1418   ("mkfs", (RErr, [String "fstype"; Device "device"]), 42, [],
1419    [InitEmpty, Always, TestOutput (
1420       [["part_disk"; "/dev/sda"; "mbr"];
1421        ["mkfs"; "ext2"; "/dev/sda1"];
1422        ["mount"; "/dev/sda1"; "/"];
1423        ["write_file"; "/new"; "new file contents"; "0"];
1424        ["cat"; "/new"]], "new file contents")],
1425    "make a filesystem",
1426    "\
1427 This creates a filesystem on C<device> (usually a partition
1428 or LVM logical volume).  The filesystem type is C<fstype>, for
1429 example C<ext3>.");
1430
1431   ("sfdisk", (RErr, [Device "device";
1432                      Int "cyls"; Int "heads"; Int "sectors";
1433                      StringList "lines"]), 43, [DangerWillRobinson],
1434    [],
1435    "create partitions on a block device",
1436    "\
1437 This is a direct interface to the L<sfdisk(8)> program for creating
1438 partitions on block devices.
1439
1440 C<device> should be a block device, for example C</dev/sda>.
1441
1442 C<cyls>, C<heads> and C<sectors> are the number of cylinders, heads
1443 and sectors on the device, which are passed directly to sfdisk as
1444 the I<-C>, I<-H> and I<-S> parameters.  If you pass C<0> for any
1445 of these, then the corresponding parameter is omitted.  Usually for
1446 'large' disks, you can just pass C<0> for these, but for small
1447 (floppy-sized) disks, sfdisk (or rather, the kernel) cannot work
1448 out the right geometry and you will need to tell it.
1449
1450 C<lines> is a list of lines that we feed to C<sfdisk>.  For more
1451 information refer to the L<sfdisk(8)> manpage.
1452
1453 To create a single partition occupying the whole disk, you would
1454 pass C<lines> as a single element list, when the single element being
1455 the string C<,> (comma).
1456
1457 See also: C<guestfs_sfdisk_l>, C<guestfs_sfdisk_N>,
1458 C<guestfs_part_init>");
1459
1460   ("write_file", (RErr, [Pathname "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning],
1461    [InitBasicFS, Always, TestOutput (
1462       [["write_file"; "/new"; "new file contents"; "0"];
1463        ["cat"; "/new"]], "new file contents");
1464     InitBasicFS, Always, TestOutput (
1465       [["write_file"; "/new"; "\nnew file contents\n"; "0"];
1466        ["cat"; "/new"]], "\nnew file contents\n");
1467     InitBasicFS, Always, TestOutput (
1468       [["write_file"; "/new"; "\n\n"; "0"];
1469        ["cat"; "/new"]], "\n\n");
1470     InitBasicFS, Always, TestOutput (
1471       [["write_file"; "/new"; ""; "0"];
1472        ["cat"; "/new"]], "");
1473     InitBasicFS, Always, TestOutput (
1474       [["write_file"; "/new"; "\n\n\n"; "0"];
1475        ["cat"; "/new"]], "\n\n\n");
1476     InitBasicFS, Always, TestOutput (
1477       [["write_file"; "/new"; "\n"; "0"];
1478        ["cat"; "/new"]], "\n")],
1479    "create a file",
1480    "\
1481 This call creates a file called C<path>.  The contents of the
1482 file is the string C<content> (which can contain any 8 bit data),
1483 with length C<size>.
1484
1485 As a special case, if C<size> is C<0>
1486 then the length is calculated using C<strlen> (so in this case
1487 the content cannot contain embedded ASCII NULs).
1488
1489 I<NB.> Owing to a bug, writing content containing ASCII NUL
1490 characters does I<not> work, even if the length is specified.
1491 We hope to resolve this bug in a future version.  In the meantime
1492 use C<guestfs_upload>.");
1493
1494   ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"],
1495    [InitEmpty, Always, TestOutputListOfDevices (
1496       [["part_disk"; "/dev/sda"; "mbr"];
1497        ["mkfs"; "ext2"; "/dev/sda1"];
1498        ["mount"; "/dev/sda1"; "/"];
1499        ["mounts"]], ["/dev/sda1"]);
1500     InitEmpty, Always, TestOutputList (
1501       [["part_disk"; "/dev/sda"; "mbr"];
1502        ["mkfs"; "ext2"; "/dev/sda1"];
1503        ["mount"; "/dev/sda1"; "/"];
1504        ["umount"; "/"];
1505        ["mounts"]], [])],
1506    "unmount a filesystem",
1507    "\
1508 This unmounts the given filesystem.  The filesystem may be
1509 specified either by its mountpoint (path) or the device which
1510 contains the filesystem.");
1511
1512   ("mounts", (RStringList "devices", []), 46, [],
1513    [InitBasicFS, Always, TestOutputListOfDevices (
1514       [["mounts"]], ["/dev/sda1"])],
1515    "show mounted filesystems",
1516    "\
1517 This returns the list of currently mounted filesystems.  It returns
1518 the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
1519
1520 Some internal mounts are not shown.
1521
1522 See also: C<guestfs_mountpoints>");
1523
1524   ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"],
1525    [InitBasicFS, Always, TestOutputList (
1526       [["umount_all"];
1527        ["mounts"]], []);
1528     (* check that umount_all can unmount nested mounts correctly: *)
1529     InitEmpty, Always, TestOutputList (
1530       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1531        ["mkfs"; "ext2"; "/dev/sda1"];
1532        ["mkfs"; "ext2"; "/dev/sda2"];
1533        ["mkfs"; "ext2"; "/dev/sda3"];
1534        ["mount"; "/dev/sda1"; "/"];
1535        ["mkdir"; "/mp1"];
1536        ["mount"; "/dev/sda2"; "/mp1"];
1537        ["mkdir"; "/mp1/mp2"];
1538        ["mount"; "/dev/sda3"; "/mp1/mp2"];
1539        ["mkdir"; "/mp1/mp2/mp3"];
1540        ["umount_all"];
1541        ["mounts"]], [])],
1542    "unmount all filesystems",
1543    "\
1544 This unmounts all mounted filesystems.
1545
1546 Some internal mounts are not unmounted by this call.");
1547
1548   ("lvm_remove_all", (RErr, []), 48, [DangerWillRobinson; Optional "lvm2"],
1549    [],
1550    "remove all LVM LVs, VGs and PVs",
1551    "\
1552 This command removes all LVM logical volumes, volume groups
1553 and physical volumes.");
1554
1555   ("file", (RString "description", [Dev_or_Path "path"]), 49, [],
1556    [InitISOFS, Always, TestOutput (
1557       [["file"; "/empty"]], "empty");
1558     InitISOFS, Always, TestOutput (
1559       [["file"; "/known-1"]], "ASCII text");
1560     InitISOFS, Always, TestLastFail (
1561       [["file"; "/notexists"]])],
1562    "determine file type",
1563    "\
1564 This call uses the standard L<file(1)> command to determine
1565 the type or contents of the file.  This also works on devices,
1566 for example to find out whether a partition contains a filesystem.
1567
1568 This call will also transparently look inside various types
1569 of compressed file.
1570
1571 The exact command which runs is C<file -zbsL path>.  Note in
1572 particular that the filename is not prepended to the output
1573 (the C<-b> option).");
1574
1575   ("command", (RString "output", [StringList "arguments"]), 50, [ProtocolLimitWarning],
1576    [InitBasicFS, Always, TestOutput (
1577       [["upload"; "test-command"; "/test-command"];
1578        ["chmod"; "0o755"; "/test-command"];
1579        ["command"; "/test-command 1"]], "Result1");
1580     InitBasicFS, Always, TestOutput (
1581       [["upload"; "test-command"; "/test-command"];
1582        ["chmod"; "0o755"; "/test-command"];
1583        ["command"; "/test-command 2"]], "Result2\n");
1584     InitBasicFS, Always, TestOutput (
1585       [["upload"; "test-command"; "/test-command"];
1586        ["chmod"; "0o755"; "/test-command"];
1587        ["command"; "/test-command 3"]], "\nResult3");
1588     InitBasicFS, Always, TestOutput (
1589       [["upload"; "test-command"; "/test-command"];
1590        ["chmod"; "0o755"; "/test-command"];
1591        ["command"; "/test-command 4"]], "\nResult4\n");
1592     InitBasicFS, Always, TestOutput (
1593       [["upload"; "test-command"; "/test-command"];
1594        ["chmod"; "0o755"; "/test-command"];
1595        ["command"; "/test-command 5"]], "\nResult5\n\n");
1596     InitBasicFS, Always, TestOutput (
1597       [["upload"; "test-command"; "/test-command"];
1598        ["chmod"; "0o755"; "/test-command"];
1599        ["command"; "/test-command 6"]], "\n\nResult6\n\n");
1600     InitBasicFS, Always, TestOutput (
1601       [["upload"; "test-command"; "/test-command"];
1602        ["chmod"; "0o755"; "/test-command"];
1603        ["command"; "/test-command 7"]], "");
1604     InitBasicFS, Always, TestOutput (
1605       [["upload"; "test-command"; "/test-command"];
1606        ["chmod"; "0o755"; "/test-command"];
1607        ["command"; "/test-command 8"]], "\n");
1608     InitBasicFS, Always, TestOutput (
1609       [["upload"; "test-command"; "/test-command"];
1610        ["chmod"; "0o755"; "/test-command"];
1611        ["command"; "/test-command 9"]], "\n\n");
1612     InitBasicFS, Always, TestOutput (
1613       [["upload"; "test-command"; "/test-command"];
1614        ["chmod"; "0o755"; "/test-command"];
1615        ["command"; "/test-command 10"]], "Result10-1\nResult10-2\n");
1616     InitBasicFS, Always, TestOutput (
1617       [["upload"; "test-command"; "/test-command"];
1618        ["chmod"; "0o755"; "/test-command"];
1619        ["command"; "/test-command 11"]], "Result11-1\nResult11-2");
1620     InitBasicFS, Always, TestLastFail (
1621       [["upload"; "test-command"; "/test-command"];
1622        ["chmod"; "0o755"; "/test-command"];
1623        ["command"; "/test-command"]])],
1624    "run a command from the guest filesystem",
1625    "\
1626 This call runs a command from the guest filesystem.  The
1627 filesystem must be mounted, and must contain a compatible
1628 operating system (ie. something Linux, with the same
1629 or compatible processor architecture).
1630
1631 The single parameter is an argv-style list of arguments.
1632 The first element is the name of the program to run.
1633 Subsequent elements are parameters.  The list must be
1634 non-empty (ie. must contain a program name).  Note that
1635 the command runs directly, and is I<not> invoked via
1636 the shell (see C<guestfs_sh>).
1637
1638 The return value is anything printed to I<stdout> by
1639 the command.
1640
1641 If the command returns a non-zero exit status, then
1642 this function returns an error message.  The error message
1643 string is the content of I<stderr> from the command.
1644
1645 The C<$PATH> environment variable will contain at least
1646 C</usr/bin> and C</bin>.  If you require a program from
1647 another location, you should provide the full path in the
1648 first parameter.
1649
1650 Shared libraries and data files required by the program
1651 must be available on filesystems which are mounted in the
1652 correct places.  It is the caller's responsibility to ensure
1653 all filesystems that are needed are mounted at the right
1654 locations.");
1655
1656   ("command_lines", (RStringList "lines", [StringList "arguments"]), 51, [ProtocolLimitWarning],
1657    [InitBasicFS, Always, TestOutputList (
1658       [["upload"; "test-command"; "/test-command"];
1659        ["chmod"; "0o755"; "/test-command"];
1660        ["command_lines"; "/test-command 1"]], ["Result1"]);
1661     InitBasicFS, Always, TestOutputList (
1662       [["upload"; "test-command"; "/test-command"];
1663        ["chmod"; "0o755"; "/test-command"];
1664        ["command_lines"; "/test-command 2"]], ["Result2"]);
1665     InitBasicFS, Always, TestOutputList (
1666       [["upload"; "test-command"; "/test-command"];
1667        ["chmod"; "0o755"; "/test-command"];
1668        ["command_lines"; "/test-command 3"]], ["";"Result3"]);
1669     InitBasicFS, Always, TestOutputList (
1670       [["upload"; "test-command"; "/test-command"];
1671        ["chmod"; "0o755"; "/test-command"];
1672        ["command_lines"; "/test-command 4"]], ["";"Result4"]);
1673     InitBasicFS, Always, TestOutputList (
1674       [["upload"; "test-command"; "/test-command"];
1675        ["chmod"; "0o755"; "/test-command"];
1676        ["command_lines"; "/test-command 5"]], ["";"Result5";""]);
1677     InitBasicFS, Always, TestOutputList (
1678       [["upload"; "test-command"; "/test-command"];
1679        ["chmod"; "0o755"; "/test-command"];
1680        ["command_lines"; "/test-command 6"]], ["";"";"Result6";""]);
1681     InitBasicFS, Always, TestOutputList (
1682       [["upload"; "test-command"; "/test-command"];
1683        ["chmod"; "0o755"; "/test-command"];
1684        ["command_lines"; "/test-command 7"]], []);
1685     InitBasicFS, Always, TestOutputList (
1686       [["upload"; "test-command"; "/test-command"];
1687        ["chmod"; "0o755"; "/test-command"];
1688        ["command_lines"; "/test-command 8"]], [""]);
1689     InitBasicFS, Always, TestOutputList (
1690       [["upload"; "test-command"; "/test-command"];
1691        ["chmod"; "0o755"; "/test-command"];
1692        ["command_lines"; "/test-command 9"]], ["";""]);
1693     InitBasicFS, Always, TestOutputList (
1694       [["upload"; "test-command"; "/test-command"];
1695        ["chmod"; "0o755"; "/test-command"];
1696        ["command_lines"; "/test-command 10"]], ["Result10-1";"Result10-2"]);
1697     InitBasicFS, Always, TestOutputList (
1698       [["upload"; "test-command"; "/test-command"];
1699        ["chmod"; "0o755"; "/test-command"];
1700        ["command_lines"; "/test-command 11"]], ["Result11-1";"Result11-2"])],
1701    "run a command, returning lines",
1702    "\
1703 This is the same as C<guestfs_command>, but splits the
1704 result into a list of lines.
1705
1706 See also: C<guestfs_sh_lines>");
1707
1708   ("stat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 52, [],
1709    [InitISOFS, Always, TestOutputStruct (
1710       [["stat"; "/empty"]], [CompareWithInt ("size", 0)])],
1711    "get file information",
1712    "\
1713 Returns file information for the given C<path>.
1714
1715 This is the same as the C<stat(2)> system call.");
1716
1717   ("lstat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 53, [],
1718    [InitISOFS, Always, TestOutputStruct (
1719       [["lstat"; "/empty"]], [CompareWithInt ("size", 0)])],
1720    "get file information for a symbolic link",
1721    "\
1722 Returns file information for the given C<path>.
1723
1724 This is the same as C<guestfs_stat> except that if C<path>
1725 is a symbolic link, then the link is stat-ed, not the file it
1726 refers to.
1727
1728 This is the same as the C<lstat(2)> system call.");
1729
1730   ("statvfs", (RStruct ("statbuf", "statvfs"), [Pathname "path"]), 54, [],
1731    [InitISOFS, Always, TestOutputStruct (
1732       [["statvfs"; "/"]], [CompareWithInt ("namemax", 255)])],
1733    "get file system statistics",
1734    "\
1735 Returns file system statistics for any mounted file system.
1736 C<path> should be a file or directory in the mounted file system
1737 (typically it is the mount point itself, but it doesn't need to be).
1738
1739 This is the same as the C<statvfs(2)> system call.");
1740
1741   ("tune2fs_l", (RHashtable "superblock", [Device "device"]), 55, [],
1742    [], (* XXX test *)
1743    "get ext2/ext3/ext4 superblock details",
1744    "\
1745 This returns the contents of the ext2, ext3 or ext4 filesystem
1746 superblock on C<device>.
1747
1748 It is the same as running C<tune2fs -l device>.  See L<tune2fs(8)>
1749 manpage for more details.  The list of fields returned isn't
1750 clearly defined, and depends on both the version of C<tune2fs>
1751 that libguestfs was built against, and the filesystem itself.");
1752
1753   ("blockdev_setro", (RErr, [Device "device"]), 56, [],
1754    [InitEmpty, Always, TestOutputTrue (
1755       [["blockdev_setro"; "/dev/sda"];
1756        ["blockdev_getro"; "/dev/sda"]])],
1757    "set block device to read-only",
1758    "\
1759 Sets the block device named C<device> to read-only.
1760
1761 This uses the L<blockdev(8)> command.");
1762
1763   ("blockdev_setrw", (RErr, [Device "device"]), 57, [],
1764    [InitEmpty, Always, TestOutputFalse (
1765       [["blockdev_setrw"; "/dev/sda"];
1766        ["blockdev_getro"; "/dev/sda"]])],
1767    "set block device to read-write",
1768    "\
1769 Sets the block device named C<device> to read-write.
1770
1771 This uses the L<blockdev(8)> command.");
1772
1773   ("blockdev_getro", (RBool "ro", [Device "device"]), 58, [],
1774    [InitEmpty, Always, TestOutputTrue (
1775       [["blockdev_setro"; "/dev/sda"];
1776        ["blockdev_getro"; "/dev/sda"]])],
1777    "is block device set to read-only",
1778    "\
1779 Returns a boolean indicating if the block device is read-only
1780 (true if read-only, false if not).
1781
1782 This uses the L<blockdev(8)> command.");
1783
1784   ("blockdev_getss", (RInt "sectorsize", [Device "device"]), 59, [],
1785    [InitEmpty, Always, TestOutputInt (
1786       [["blockdev_getss"; "/dev/sda"]], 512)],
1787    "get sectorsize of block device",
1788    "\
1789 This returns the size of sectors on a block device.
1790 Usually 512, but can be larger for modern devices.
1791
1792 (Note, this is not the size in sectors, use C<guestfs_blockdev_getsz>
1793 for that).
1794
1795 This uses the L<blockdev(8)> command.");
1796
1797   ("blockdev_getbsz", (RInt "blocksize", [Device "device"]), 60, [],
1798    [InitEmpty, Always, TestOutputInt (
1799       [["blockdev_getbsz"; "/dev/sda"]], 4096)],
1800    "get blocksize of block device",
1801    "\
1802 This returns the block size of a device.
1803
1804 (Note this is different from both I<size in blocks> and
1805 I<filesystem block size>).
1806
1807 This uses the L<blockdev(8)> command.");
1808
1809   ("blockdev_setbsz", (RErr, [Device "device"; Int "blocksize"]), 61, [],
1810    [], (* XXX test *)
1811    "set blocksize of block device",
1812    "\
1813 This sets the block size of a device.
1814
1815 (Note this is different from both I<size in blocks> and
1816 I<filesystem block size>).
1817
1818 This uses the L<blockdev(8)> command.");
1819
1820   ("blockdev_getsz", (RInt64 "sizeinsectors", [Device "device"]), 62, [],
1821    [InitEmpty, Always, TestOutputInt (
1822       [["blockdev_getsz"; "/dev/sda"]], 1024000)],
1823    "get total size of device in 512-byte sectors",
1824    "\
1825 This returns the size of the device in units of 512-byte sectors
1826 (even if the sectorsize isn't 512 bytes ... weird).
1827
1828 See also C<guestfs_blockdev_getss> for the real sector size of
1829 the device, and C<guestfs_blockdev_getsize64> for the more
1830 useful I<size in bytes>.
1831
1832 This uses the L<blockdev(8)> command.");
1833
1834   ("blockdev_getsize64", (RInt64 "sizeinbytes", [Device "device"]), 63, [],
1835    [InitEmpty, Always, TestOutputInt (
1836       [["blockdev_getsize64"; "/dev/sda"]], 524288000)],
1837    "get total size of device in bytes",
1838    "\
1839 This returns the size of the device in bytes.
1840
1841 See also C<guestfs_blockdev_getsz>.
1842
1843 This uses the L<blockdev(8)> command.");
1844
1845   ("blockdev_flushbufs", (RErr, [Device "device"]), 64, [],
1846    [InitEmpty, Always, TestRun
1847       [["blockdev_flushbufs"; "/dev/sda"]]],
1848    "flush device buffers",
1849    "\
1850 This tells the kernel to flush internal buffers associated
1851 with C<device>.
1852
1853 This uses the L<blockdev(8)> command.");
1854
1855   ("blockdev_rereadpt", (RErr, [Device "device"]), 65, [],
1856    [InitEmpty, Always, TestRun
1857       [["blockdev_rereadpt"; "/dev/sda"]]],
1858    "reread partition table",
1859    "\
1860 Reread the partition table on C<device>.
1861
1862 This uses the L<blockdev(8)> command.");
1863
1864   ("upload", (RErr, [FileIn "filename"; Dev_or_Path "remotefilename"]), 66, [],
1865    [InitBasicFS, Always, TestOutput (
1866       (* Pick a file from cwd which isn't likely to change. *)
1867       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1868        ["checksum"; "md5"; "/COPYING.LIB"]],
1869         Digest.to_hex (Digest.file "COPYING.LIB"))],
1870    "upload a file from the local machine",
1871    "\
1872 Upload local file C<filename> to C<remotefilename> on the
1873 filesystem.
1874
1875 C<filename> can also be a named pipe.
1876
1877 See also C<guestfs_download>.");
1878
1879   ("download", (RErr, [Dev_or_Path "remotefilename"; FileOut "filename"]), 67, [],
1880    [InitBasicFS, Always, TestOutput (
1881       (* Pick a file from cwd which isn't likely to change. *)
1882       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1883        ["download"; "/COPYING.LIB"; "testdownload.tmp"];
1884        ["upload"; "testdownload.tmp"; "/upload"];
1885        ["checksum"; "md5"; "/upload"]],
1886         Digest.to_hex (Digest.file "COPYING.LIB"))],
1887    "download a file to the local machine",
1888    "\
1889 Download file C<remotefilename> and save it as C<filename>
1890 on the local machine.
1891
1892 C<filename> can also be a named pipe.
1893
1894 See also C<guestfs_upload>, C<guestfs_cat>.");
1895
1896   ("checksum", (RString "checksum", [String "csumtype"; Pathname "path"]), 68, [],
1897    [InitISOFS, Always, TestOutput (
1898       [["checksum"; "crc"; "/known-3"]], "2891671662");
1899     InitISOFS, Always, TestLastFail (
1900       [["checksum"; "crc"; "/notexists"]]);
1901     InitISOFS, Always, TestOutput (
1902       [["checksum"; "md5"; "/known-3"]], "46d6ca27ee07cdc6fa99c2e138cc522c");
1903     InitISOFS, Always, TestOutput (
1904       [["checksum"; "sha1"; "/known-3"]], "b7ebccc3ee418311091c3eda0a45b83c0a770f15");
1905     InitISOFS, Always, TestOutput (
1906       [["checksum"; "sha224"; "/known-3"]], "d2cd1774b28f3659c14116be0a6dc2bb5c4b350ce9cd5defac707741");
1907     InitISOFS, Always, TestOutput (
1908       [["checksum"; "sha256"; "/known-3"]], "75bb71b90cd20cb13f86d2bea8dad63ac7194e7517c3b52b8d06ff52d3487d30");
1909     InitISOFS, Always, TestOutput (
1910       [["checksum"; "sha384"; "/known-3"]], "5fa7883430f357b5d7b7271d3a1d2872b51d73cba72731de6863d3dea55f30646af2799bef44d5ea776a5ec7941ac640");
1911     InitISOFS, Always, TestOutput (
1912       [["checksum"; "sha512"; "/known-3"]], "2794062c328c6b216dca90443b7f7134c5f40e56bd0ed7853123275a09982a6f992e6ca682f9d2fba34a4c5e870d8fe077694ff831e3032a004ee077e00603f6")],
1913    "compute MD5, SHAx or CRC checksum of file",
1914    "\
1915 This call computes the MD5, SHAx or CRC checksum of the
1916 file named C<path>.
1917
1918 The type of checksum to compute is given by the C<csumtype>
1919 parameter which must have one of the following values:
1920
1921 =over 4
1922
1923 =item C<crc>
1924
1925 Compute the cyclic redundancy check (CRC) specified by POSIX
1926 for the C<cksum> command.
1927
1928 =item C<md5>
1929
1930 Compute the MD5 hash (using the C<md5sum> program).
1931
1932 =item C<sha1>
1933
1934 Compute the SHA1 hash (using the C<sha1sum> program).
1935
1936 =item C<sha224>
1937
1938 Compute the SHA224 hash (using the C<sha224sum> program).
1939
1940 =item C<sha256>
1941
1942 Compute the SHA256 hash (using the C<sha256sum> program).
1943
1944 =item C<sha384>
1945
1946 Compute the SHA384 hash (using the C<sha384sum> program).
1947
1948 =item C<sha512>
1949
1950 Compute the SHA512 hash (using the C<sha512sum> program).
1951
1952 =back
1953
1954 The checksum is returned as a printable string.");
1955
1956   ("tar_in", (RErr, [FileIn "tarfile"; String "directory"]), 69, [],
1957    [InitBasicFS, Always, TestOutput (
1958       [["tar_in"; "../images/helloworld.tar"; "/"];
1959        ["cat"; "/hello"]], "hello\n")],
1960    "unpack tarfile to directory",
1961    "\
1962 This command uploads and unpacks local file C<tarfile> (an
1963 I<uncompressed> tar file) into C<directory>.
1964
1965 To upload a compressed tarball, use C<guestfs_tgz_in>.");
1966
1967   ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [],
1968    [],
1969    "pack directory into tarfile",
1970    "\
1971 This command packs the contents of C<directory> and downloads
1972 it to local file C<tarfile>.
1973
1974 To download a compressed tarball, use C<guestfs_tgz_out>.");
1975
1976   ("tgz_in", (RErr, [FileIn "tarball"; String "directory"]), 71, [],
1977    [InitBasicFS, Always, TestOutput (
1978       [["tgz_in"; "../images/helloworld.tar.gz"; "/"];
1979        ["cat"; "/hello"]], "hello\n")],
1980    "unpack compressed tarball to directory",
1981    "\
1982 This command uploads and unpacks local file C<tarball> (a
1983 I<gzip compressed> tar file) into C<directory>.
1984
1985 To upload an uncompressed tarball, use C<guestfs_tar_in>.");
1986
1987   ("tgz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 72, [],
1988    [],
1989    "pack directory into compressed tarball",
1990    "\
1991 This command packs the contents of C<directory> and downloads
1992 it to local file C<tarball>.
1993
1994 To download an uncompressed tarball, use C<guestfs_tar_out>.");
1995
1996   ("mount_ro", (RErr, [Device "device"; String "mountpoint"]), 73, [],
1997    [InitBasicFS, Always, TestLastFail (
1998       [["umount"; "/"];
1999        ["mount_ro"; "/dev/sda1"; "/"];
2000        ["touch"; "/new"]]);
2001     InitBasicFS, Always, TestOutput (
2002       [["write_file"; "/new"; "data"; "0"];
2003        ["umount"; "/"];
2004        ["mount_ro"; "/dev/sda1"; "/"];
2005        ["cat"; "/new"]], "data")],
2006    "mount a guest disk, read-only",
2007    "\
2008 This is the same as the C<guestfs_mount> command, but it
2009 mounts the filesystem with the read-only (I<-o ro>) flag.");
2010
2011   ("mount_options", (RErr, [String "options"; Device "device"; String "mountpoint"]), 74, [],
2012    [],
2013    "mount a guest disk with mount options",
2014    "\
2015 This is the same as the C<guestfs_mount> command, but it
2016 allows you to set the mount options as for the
2017 L<mount(8)> I<-o> flag.");
2018
2019   ("mount_vfs", (RErr, [String "options"; String "vfstype"; Device "device"; String "mountpoint"]), 75, [],
2020    [],
2021    "mount a guest disk with mount options and vfstype",
2022    "\
2023 This is the same as the C<guestfs_mount> command, but it
2024 allows you to set both the mount options and the vfstype
2025 as for the L<mount(8)> I<-o> and I<-t> flags.");
2026
2027   ("debug", (RString "result", [String "subcmd"; StringList "extraargs"]), 76, [],
2028    [],
2029    "debugging and internals",
2030    "\
2031 The C<guestfs_debug> command exposes some internals of
2032 C<guestfsd> (the guestfs daemon) that runs inside the
2033 qemu subprocess.
2034
2035 There is no comprehensive help for this command.  You have
2036 to look at the file C<daemon/debug.c> in the libguestfs source
2037 to find out what you can do.");
2038
2039   ("lvremove", (RErr, [Device "device"]), 77, [Optional "lvm2"],
2040    [InitEmpty, Always, TestOutputList (
2041       [["part_disk"; "/dev/sda"; "mbr"];
2042        ["pvcreate"; "/dev/sda1"];
2043        ["vgcreate"; "VG"; "/dev/sda1"];
2044        ["lvcreate"; "LV1"; "VG"; "50"];
2045        ["lvcreate"; "LV2"; "VG"; "50"];
2046        ["lvremove"; "/dev/VG/LV1"];
2047        ["lvs"]], ["/dev/VG/LV2"]);
2048     InitEmpty, Always, TestOutputList (
2049       [["part_disk"; "/dev/sda"; "mbr"];
2050        ["pvcreate"; "/dev/sda1"];
2051        ["vgcreate"; "VG"; "/dev/sda1"];
2052        ["lvcreate"; "LV1"; "VG"; "50"];
2053        ["lvcreate"; "LV2"; "VG"; "50"];
2054        ["lvremove"; "/dev/VG"];
2055        ["lvs"]], []);
2056     InitEmpty, Always, TestOutputList (
2057       [["part_disk"; "/dev/sda"; "mbr"];
2058        ["pvcreate"; "/dev/sda1"];
2059        ["vgcreate"; "VG"; "/dev/sda1"];
2060        ["lvcreate"; "LV1"; "VG"; "50"];
2061        ["lvcreate"; "LV2"; "VG"; "50"];
2062        ["lvremove"; "/dev/VG"];
2063        ["vgs"]], ["VG"])],
2064    "remove an LVM logical volume",
2065    "\
2066 Remove an LVM logical volume C<device>, where C<device> is
2067 the path to the LV, such as C</dev/VG/LV>.
2068
2069 You can also remove all LVs in a volume group by specifying
2070 the VG name, C</dev/VG>.");
2071
2072   ("vgremove", (RErr, [String "vgname"]), 78, [Optional "lvm2"],
2073    [InitEmpty, Always, TestOutputList (
2074       [["part_disk"; "/dev/sda"; "mbr"];
2075        ["pvcreate"; "/dev/sda1"];
2076        ["vgcreate"; "VG"; "/dev/sda1"];
2077        ["lvcreate"; "LV1"; "VG"; "50"];
2078        ["lvcreate"; "LV2"; "VG"; "50"];
2079        ["vgremove"; "VG"];
2080        ["lvs"]], []);
2081     InitEmpty, Always, TestOutputList (
2082       [["part_disk"; "/dev/sda"; "mbr"];
2083        ["pvcreate"; "/dev/sda1"];
2084        ["vgcreate"; "VG"; "/dev/sda1"];
2085        ["lvcreate"; "LV1"; "VG"; "50"];
2086        ["lvcreate"; "LV2"; "VG"; "50"];
2087        ["vgremove"; "VG"];
2088        ["vgs"]], [])],
2089    "remove an LVM volume group",
2090    "\
2091 Remove an LVM volume group C<vgname>, (for example C<VG>).
2092
2093 This also forcibly removes all logical volumes in the volume
2094 group (if any).");
2095
2096   ("pvremove", (RErr, [Device "device"]), 79, [Optional "lvm2"],
2097    [InitEmpty, Always, TestOutputListOfDevices (
2098       [["part_disk"; "/dev/sda"; "mbr"];
2099        ["pvcreate"; "/dev/sda1"];
2100        ["vgcreate"; "VG"; "/dev/sda1"];
2101        ["lvcreate"; "LV1"; "VG"; "50"];
2102        ["lvcreate"; "LV2"; "VG"; "50"];
2103        ["vgremove"; "VG"];
2104        ["pvremove"; "/dev/sda1"];
2105        ["lvs"]], []);
2106     InitEmpty, Always, TestOutputListOfDevices (
2107       [["part_disk"; "/dev/sda"; "mbr"];
2108        ["pvcreate"; "/dev/sda1"];
2109        ["vgcreate"; "VG"; "/dev/sda1"];
2110        ["lvcreate"; "LV1"; "VG"; "50"];
2111        ["lvcreate"; "LV2"; "VG"; "50"];
2112        ["vgremove"; "VG"];
2113        ["pvremove"; "/dev/sda1"];
2114        ["vgs"]], []);
2115     InitEmpty, Always, TestOutputListOfDevices (
2116       [["part_disk"; "/dev/sda"; "mbr"];
2117        ["pvcreate"; "/dev/sda1"];
2118        ["vgcreate"; "VG"; "/dev/sda1"];
2119        ["lvcreate"; "LV1"; "VG"; "50"];
2120        ["lvcreate"; "LV2"; "VG"; "50"];
2121        ["vgremove"; "VG"];
2122        ["pvremove"; "/dev/sda1"];
2123        ["pvs"]], [])],
2124    "remove an LVM physical volume",
2125    "\
2126 This wipes a physical volume C<device> so that LVM will no longer
2127 recognise it.
2128
2129 The implementation uses the C<pvremove> command which refuses to
2130 wipe physical volumes that contain any volume groups, so you have
2131 to remove those first.");
2132
2133   ("set_e2label", (RErr, [Device "device"; String "label"]), 80, [],
2134    [InitBasicFS, Always, TestOutput (
2135       [["set_e2label"; "/dev/sda1"; "testlabel"];
2136        ["get_e2label"; "/dev/sda1"]], "testlabel")],
2137    "set the ext2/3/4 filesystem label",
2138    "\
2139 This sets the ext2/3/4 filesystem label of the filesystem on
2140 C<device> to C<label>.  Filesystem labels are limited to
2141 16 characters.
2142
2143 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2label>
2144 to return the existing label on a filesystem.");
2145
2146   ("get_e2label", (RString "label", [Device "device"]), 81, [],
2147    [],
2148    "get the ext2/3/4 filesystem label",
2149    "\
2150 This returns the ext2/3/4 filesystem label of the filesystem on
2151 C<device>.");
2152
2153   ("set_e2uuid", (RErr, [Device "device"; String "uuid"]), 82, [],
2154    (let uuid = uuidgen () in
2155     [InitBasicFS, Always, TestOutput (
2156        [["set_e2uuid"; "/dev/sda1"; uuid];
2157         ["get_e2uuid"; "/dev/sda1"]], uuid);
2158      InitBasicFS, Always, TestOutput (
2159        [["set_e2uuid"; "/dev/sda1"; "clear"];
2160         ["get_e2uuid"; "/dev/sda1"]], "");
2161      (* We can't predict what UUIDs will be, so just check the commands run. *)
2162      InitBasicFS, Always, TestRun (
2163        [["set_e2uuid"; "/dev/sda1"; "random"]]);
2164      InitBasicFS, Always, TestRun (
2165        [["set_e2uuid"; "/dev/sda1"; "time"]])]),
2166    "set the ext2/3/4 filesystem UUID",
2167    "\
2168 This sets the ext2/3/4 filesystem UUID of the filesystem on
2169 C<device> to C<uuid>.  The format of the UUID and alternatives
2170 such as C<clear>, C<random> and C<time> are described in the
2171 L<tune2fs(8)> manpage.
2172
2173 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2uuid>
2174 to return the existing UUID of a filesystem.");
2175
2176   ("get_e2uuid", (RString "uuid", [Device "device"]), 83, [],
2177    [],
2178    "get the ext2/3/4 filesystem UUID",
2179    "\
2180 This returns the ext2/3/4 filesystem UUID of the filesystem on
2181 C<device>.");
2182
2183   ("fsck", (RInt "status", [String "fstype"; Device "device"]), 84, [],
2184    [InitBasicFS, Always, TestOutputInt (
2185       [["umount"; "/dev/sda1"];
2186        ["fsck"; "ext2"; "/dev/sda1"]], 0);
2187     InitBasicFS, Always, TestOutputInt (
2188       [["umount"; "/dev/sda1"];
2189        ["zero"; "/dev/sda1"];
2190        ["fsck"; "ext2"; "/dev/sda1"]], 8)],
2191    "run the filesystem checker",
2192    "\
2193 This runs the filesystem checker (fsck) on C<device> which
2194 should have filesystem type C<fstype>.
2195
2196 The returned integer is the status.  See L<fsck(8)> for the
2197 list of status codes from C<fsck>.
2198
2199 Notes:
2200
2201 =over 4
2202
2203 =item *
2204
2205 Multiple status codes can be summed together.
2206
2207 =item *
2208
2209 A non-zero return code can mean \"success\", for example if
2210 errors have been corrected on the filesystem.
2211
2212 =item *
2213
2214 Checking or repairing NTFS volumes is not supported
2215 (by linux-ntfs).
2216
2217 =back
2218
2219 This command is entirely equivalent to running C<fsck -a -t fstype device>.");
2220
2221   ("zero", (RErr, [Device "device"]), 85, [],
2222    [InitBasicFS, Always, TestOutput (
2223       [["umount"; "/dev/sda1"];
2224        ["zero"; "/dev/sda1"];
2225        ["file"; "/dev/sda1"]], "data")],
2226    "write zeroes to the device",
2227    "\
2228 This command writes zeroes over the first few blocks of C<device>.
2229
2230 How many blocks are zeroed isn't specified (but it's I<not> enough
2231 to securely wipe the device).  It should be sufficient to remove
2232 any partition tables, filesystem superblocks and so on.
2233
2234 See also: C<guestfs_scrub_device>.");
2235
2236   ("grub_install", (RErr, [Pathname "root"; Device "device"]), 86, [],
2237    (* Test disabled because grub-install incompatible with virtio-blk driver.
2238     * See also: https://bugzilla.redhat.com/show_bug.cgi?id=479760
2239     *)
2240    [InitBasicFS, Disabled, TestOutputTrue (
2241       [["grub_install"; "/"; "/dev/sda1"];
2242        ["is_dir"; "/boot"]])],
2243    "install GRUB",
2244    "\
2245 This command installs GRUB (the Grand Unified Bootloader) on
2246 C<device>, with the root directory being C<root>.");
2247
2248   ("cp", (RErr, [Pathname "src"; Pathname "dest"]), 87, [],
2249    [InitBasicFS, Always, TestOutput (
2250       [["write_file"; "/old"; "file content"; "0"];
2251        ["cp"; "/old"; "/new"];
2252        ["cat"; "/new"]], "file content");
2253     InitBasicFS, Always, TestOutputTrue (
2254       [["write_file"; "/old"; "file content"; "0"];
2255        ["cp"; "/old"; "/new"];
2256        ["is_file"; "/old"]]);
2257     InitBasicFS, Always, TestOutput (
2258       [["write_file"; "/old"; "file content"; "0"];
2259        ["mkdir"; "/dir"];
2260        ["cp"; "/old"; "/dir/new"];
2261        ["cat"; "/dir/new"]], "file content")],
2262    "copy a file",
2263    "\
2264 This copies a file from C<src> to C<dest> where C<dest> is
2265 either a destination filename or destination directory.");
2266
2267   ("cp_a", (RErr, [Pathname "src"; Pathname "dest"]), 88, [],
2268    [InitBasicFS, Always, TestOutput (
2269       [["mkdir"; "/olddir"];
2270        ["mkdir"; "/newdir"];
2271        ["write_file"; "/olddir/file"; "file content"; "0"];
2272        ["cp_a"; "/olddir"; "/newdir"];
2273        ["cat"; "/newdir/olddir/file"]], "file content")],
2274    "copy a file or directory recursively",
2275    "\
2276 This copies a file or directory from C<src> to C<dest>
2277 recursively using the C<cp -a> command.");
2278
2279   ("mv", (RErr, [Pathname "src"; Pathname "dest"]), 89, [],
2280    [InitBasicFS, Always, TestOutput (
2281       [["write_file"; "/old"; "file content"; "0"];
2282        ["mv"; "/old"; "/new"];
2283        ["cat"; "/new"]], "file content");
2284     InitBasicFS, Always, TestOutputFalse (
2285       [["write_file"; "/old"; "file content"; "0"];
2286        ["mv"; "/old"; "/new"];
2287        ["is_file"; "/old"]])],
2288    "move a file",
2289    "\
2290 This moves a file from C<src> to C<dest> where C<dest> is
2291 either a destination filename or destination directory.");
2292
2293   ("drop_caches", (RErr, [Int "whattodrop"]), 90, [],
2294    [InitEmpty, Always, TestRun (
2295       [["drop_caches"; "3"]])],
2296    "drop kernel page cache, dentries and inodes",
2297    "\
2298 This instructs the guest kernel to drop its page cache,
2299 and/or dentries and inode caches.  The parameter C<whattodrop>
2300 tells the kernel what precisely to drop, see
2301 L<http://linux-mm.org/Drop_Caches>
2302
2303 Setting C<whattodrop> to 3 should drop everything.
2304
2305 This automatically calls L<sync(2)> before the operation,
2306 so that the maximum guest memory is freed.");
2307
2308   ("dmesg", (RString "kmsgs", []), 91, [],
2309    [InitEmpty, Always, TestRun (
2310       [["dmesg"]])],
2311    "return kernel messages",
2312    "\
2313 This returns the kernel messages (C<dmesg> output) from
2314 the guest kernel.  This is sometimes useful for extended
2315 debugging of problems.
2316
2317 Another way to get the same information is to enable
2318 verbose messages with C<guestfs_set_verbose> or by setting
2319 the environment variable C<LIBGUESTFS_DEBUG=1> before
2320 running the program.");
2321
2322   ("ping_daemon", (RErr, []), 92, [],
2323    [InitEmpty, Always, TestRun (
2324       [["ping_daemon"]])],
2325    "ping the guest daemon",
2326    "\
2327 This is a test probe into the guestfs daemon running inside
2328 the qemu subprocess.  Calling this function checks that the
2329 daemon responds to the ping message, without affecting the daemon
2330 or attached block device(s) in any other way.");
2331
2332   ("equal", (RBool "equality", [Pathname "file1"; Pathname "file2"]), 93, [],
2333    [InitBasicFS, Always, TestOutputTrue (
2334       [["write_file"; "/file1"; "contents of a file"; "0"];
2335        ["cp"; "/file1"; "/file2"];
2336        ["equal"; "/file1"; "/file2"]]);
2337     InitBasicFS, Always, TestOutputFalse (
2338       [["write_file"; "/file1"; "contents of a file"; "0"];
2339        ["write_file"; "/file2"; "contents of another file"; "0"];
2340        ["equal"; "/file1"; "/file2"]]);
2341     InitBasicFS, Always, TestLastFail (
2342       [["equal"; "/file1"; "/file2"]])],
2343    "test if two files have equal contents",
2344    "\
2345 This compares the two files C<file1> and C<file2> and returns
2346 true if their content is exactly equal, or false otherwise.
2347
2348 The external L<cmp(1)> program is used for the comparison.");
2349
2350   ("strings", (RStringList "stringsout", [Pathname "path"]), 94, [ProtocolLimitWarning],
2351    [InitISOFS, Always, TestOutputList (
2352       [["strings"; "/known-5"]], ["abcdefghi"; "jklmnopqr"]);
2353     InitISOFS, Always, TestOutputList (
2354       [["strings"; "/empty"]], [])],
2355    "print the printable strings in a file",
2356    "\
2357 This runs the L<strings(1)> command on a file and returns
2358 the list of printable strings found.");
2359
2360   ("strings_e", (RStringList "stringsout", [String "encoding"; Pathname "path"]), 95, [ProtocolLimitWarning],
2361    [InitISOFS, Always, TestOutputList (
2362       [["strings_e"; "b"; "/known-5"]], []);
2363     InitBasicFS, Disabled, TestOutputList (
2364       [["write_file"; "/new"; "\000h\000e\000l\000l\000o\000\n\000w\000o\000r\000l\000d\000\n"; "24"];
2365        ["strings_e"; "b"; "/new"]], ["hello"; "world"])],
2366    "print the printable strings in a file",
2367    "\
2368 This is like the C<guestfs_strings> command, but allows you to
2369 specify the encoding.
2370
2371 See the L<strings(1)> manpage for the full list of encodings.
2372
2373 Commonly useful encodings are C<l> (lower case L) which will
2374 show strings inside Windows/x86 files.
2375
2376 The returned strings are transcoded to UTF-8.");
2377
2378   ("hexdump", (RString "dump", [Pathname "path"]), 96, [ProtocolLimitWarning],
2379    [InitISOFS, Always, TestOutput (
2380       [["hexdump"; "/known-4"]], "00000000  61 62 63 0a 64 65 66 0a  67 68 69                 |abc.def.ghi|\n0000000b\n");
2381     (* Test for RHBZ#501888c2 regression which caused large hexdump
2382      * commands to segfault.
2383      *)
2384     InitISOFS, Always, TestRun (
2385       [["hexdump"; "/100krandom"]])],
2386    "dump a file in hexadecimal",
2387    "\
2388 This runs C<hexdump -C> on the given C<path>.  The result is
2389 the human-readable, canonical hex dump of the file.");
2390
2391   ("zerofree", (RErr, [Device "device"]), 97, [Optional "zerofree"],
2392    [InitNone, Always, TestOutput (
2393       [["part_disk"; "/dev/sda"; "mbr"];
2394        ["mkfs"; "ext3"; "/dev/sda1"];
2395        ["mount"; "/dev/sda1"; "/"];
2396        ["write_file"; "/new"; "test file"; "0"];
2397        ["umount"; "/dev/sda1"];
2398        ["zerofree"; "/dev/sda1"];
2399        ["mount"; "/dev/sda1"; "/"];
2400        ["cat"; "/new"]], "test file")],
2401    "zero unused inodes and disk blocks on ext2/3 filesystem",
2402    "\
2403 This runs the I<zerofree> program on C<device>.  This program
2404 claims to zero unused inodes and disk blocks on an ext2/3
2405 filesystem, thus making it possible to compress the filesystem
2406 more effectively.
2407
2408 You should B<not> run this program if the filesystem is
2409 mounted.
2410
2411 It is possible that using this program can damage the filesystem
2412 or data on the filesystem.");
2413
2414   ("pvresize", (RErr, [Device "device"]), 98, [Optional "lvm2"],
2415    [],
2416    "resize an LVM physical volume",
2417    "\
2418 This resizes (expands or shrinks) an existing LVM physical
2419 volume to match the new size of the underlying device.");
2420
2421   ("sfdisk_N", (RErr, [Device "device"; Int "partnum";
2422                        Int "cyls"; Int "heads"; Int "sectors";
2423                        String "line"]), 99, [DangerWillRobinson],
2424    [],
2425    "modify a single partition on a block device",
2426    "\
2427 This runs L<sfdisk(8)> option to modify just the single
2428 partition C<n> (note: C<n> counts from 1).
2429
2430 For other parameters, see C<guestfs_sfdisk>.  You should usually
2431 pass C<0> for the cyls/heads/sectors parameters.
2432
2433 See also: C<guestfs_part_add>");
2434
2435   ("sfdisk_l", (RString "partitions", [Device "device"]), 100, [],
2436    [],
2437    "display the partition table",
2438    "\
2439 This displays the partition table on C<device>, in the
2440 human-readable output of the L<sfdisk(8)> command.  It is
2441 not intended to be parsed.
2442
2443 See also: C<guestfs_part_list>");
2444
2445   ("sfdisk_kernel_geometry", (RString "partitions", [Device "device"]), 101, [],
2446    [],
2447    "display the kernel geometry",
2448    "\
2449 This displays the kernel's idea of the geometry of C<device>.
2450
2451 The result is in human-readable format, and not designed to
2452 be parsed.");
2453
2454   ("sfdisk_disk_geometry", (RString "partitions", [Device "device"]), 102, [],
2455    [],
2456    "display the disk geometry from the partition table",
2457    "\
2458 This displays the disk geometry of C<device> read from the
2459 partition table.  Especially in the case where the underlying
2460 block device has been resized, this can be different from the
2461 kernel's idea of the geometry (see C<guestfs_sfdisk_kernel_geometry>).
2462
2463 The result is in human-readable format, and not designed to
2464 be parsed.");
2465
2466   ("vg_activate_all", (RErr, [Bool "activate"]), 103, [Optional "lvm2"],
2467    [],
2468    "activate or deactivate all volume groups",
2469    "\
2470 This command activates or (if C<activate> is false) deactivates
2471 all logical volumes in all volume groups.
2472 If activated, then they are made known to the
2473 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2474 then those devices disappear.
2475
2476 This command is the same as running C<vgchange -a y|n>");
2477
2478   ("vg_activate", (RErr, [Bool "activate"; StringList "volgroups"]), 104, [Optional "lvm2"],
2479    [],
2480    "activate or deactivate some volume groups",
2481    "\
2482 This command activates or (if C<activate> is false) deactivates
2483 all logical volumes in the listed volume groups C<volgroups>.
2484 If activated, then they are made known to the
2485 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2486 then those devices disappear.
2487
2488 This command is the same as running C<vgchange -a y|n volgroups...>
2489
2490 Note that if C<volgroups> is an empty list then B<all> volume groups
2491 are activated or deactivated.");
2492
2493   ("lvresize", (RErr, [Device "device"; Int "mbytes"]), 105, [Optional "lvm2"],
2494    [InitNone, Always, TestOutput (
2495       [["part_disk"; "/dev/sda"; "mbr"];
2496        ["pvcreate"; "/dev/sda1"];
2497        ["vgcreate"; "VG"; "/dev/sda1"];
2498        ["lvcreate"; "LV"; "VG"; "10"];
2499        ["mkfs"; "ext2"; "/dev/VG/LV"];
2500        ["mount"; "/dev/VG/LV"; "/"];
2501        ["write_file"; "/new"; "test content"; "0"];
2502        ["umount"; "/"];
2503        ["lvresize"; "/dev/VG/LV"; "20"];
2504        ["e2fsck_f"; "/dev/VG/LV"];
2505        ["resize2fs"; "/dev/VG/LV"];
2506        ["mount"; "/dev/VG/LV"; "/"];
2507        ["cat"; "/new"]], "test content")],
2508    "resize an LVM logical volume",
2509    "\
2510 This resizes (expands or shrinks) an existing LVM logical
2511 volume to C<mbytes>.  When reducing, data in the reduced part
2512 is lost.");
2513
2514   ("resize2fs", (RErr, [Device "device"]), 106, [],
2515    [], (* lvresize tests this *)
2516    "resize an ext2/ext3 filesystem",
2517    "\
2518 This resizes an ext2 or ext3 filesystem to match the size of
2519 the underlying device.
2520
2521 I<Note:> It is sometimes required that you run C<guestfs_e2fsck_f>
2522 on the C<device> before calling this command.  For unknown reasons
2523 C<resize2fs> sometimes gives an error about this and sometimes not.
2524 In any case, it is always safe to call C<guestfs_e2fsck_f> before
2525 calling this function.");
2526
2527   ("find", (RStringList "names", [Pathname "directory"]), 107, [ProtocolLimitWarning],
2528    [InitBasicFS, Always, TestOutputList (
2529       [["find"; "/"]], ["lost+found"]);
2530     InitBasicFS, Always, TestOutputList (
2531       [["touch"; "/a"];
2532        ["mkdir"; "/b"];
2533        ["touch"; "/b/c"];
2534        ["find"; "/"]], ["a"; "b"; "b/c"; "lost+found"]);
2535     InitBasicFS, Always, TestOutputList (
2536       [["mkdir_p"; "/a/b/c"];
2537        ["touch"; "/a/b/c/d"];
2538        ["find"; "/a/b/"]], ["c"; "c/d"])],
2539    "find all files and directories",
2540    "\
2541 This command lists out all files and directories, recursively,
2542 starting at C<directory>.  It is essentially equivalent to
2543 running the shell command C<find directory -print> but some
2544 post-processing happens on the output, described below.
2545
2546 This returns a list of strings I<without any prefix>.  Thus
2547 if the directory structure was:
2548
2549  /tmp/a
2550  /tmp/b
2551  /tmp/c/d
2552
2553 then the returned list from C<guestfs_find> C</tmp> would be
2554 4 elements:
2555
2556  a
2557  b
2558  c
2559  c/d
2560
2561 If C<directory> is not a directory, then this command returns
2562 an error.
2563
2564 The returned list is sorted.
2565
2566 See also C<guestfs_find0>.");
2567
2568   ("e2fsck_f", (RErr, [Device "device"]), 108, [],
2569    [], (* lvresize tests this *)
2570    "check an ext2/ext3 filesystem",
2571    "\
2572 This runs C<e2fsck -p -f device>, ie. runs the ext2/ext3
2573 filesystem checker on C<device>, noninteractively (C<-p>),
2574 even if the filesystem appears to be clean (C<-f>).
2575
2576 This command is only needed because of C<guestfs_resize2fs>
2577 (q.v.).  Normally you should use C<guestfs_fsck>.");
2578
2579   ("sleep", (RErr, [Int "secs"]), 109, [],
2580    [InitNone, Always, TestRun (
2581       [["sleep"; "1"]])],
2582    "sleep for some seconds",
2583    "\
2584 Sleep for C<secs> seconds.");
2585
2586   ("ntfs_3g_probe", (RInt "status", [Bool "rw"; Device "device"]), 110, [Optional "ntfs3g"],
2587    [InitNone, Always, TestOutputInt (
2588       [["part_disk"; "/dev/sda"; "mbr"];
2589        ["mkfs"; "ntfs"; "/dev/sda1"];
2590        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 0);
2591     InitNone, Always, TestOutputInt (
2592       [["part_disk"; "/dev/sda"; "mbr"];
2593        ["mkfs"; "ext2"; "/dev/sda1"];
2594        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 12)],
2595    "probe NTFS volume",
2596    "\
2597 This command runs the L<ntfs-3g.probe(8)> command which probes
2598 an NTFS C<device> for mountability.  (Not all NTFS volumes can
2599 be mounted read-write, and some cannot be mounted at all).
2600
2601 C<rw> is a boolean flag.  Set it to true if you want to test
2602 if the volume can be mounted read-write.  Set it to false if
2603 you want to test if the volume can be mounted read-only.
2604
2605 The return value is an integer which C<0> if the operation
2606 would succeed, or some non-zero value documented in the
2607 L<ntfs-3g.probe(8)> manual page.");
2608
2609   ("sh", (RString "output", [String "command"]), 111, [],
2610    [], (* XXX needs tests *)
2611    "run a command via the shell",
2612    "\
2613 This call runs a command from the guest filesystem via the
2614 guest's C</bin/sh>.
2615
2616 This is like C<guestfs_command>, but passes the command to:
2617
2618  /bin/sh -c \"command\"
2619
2620 Depending on the guest's shell, this usually results in
2621 wildcards being expanded, shell expressions being interpolated
2622 and so on.
2623
2624 All the provisos about C<guestfs_command> apply to this call.");
2625
2626   ("sh_lines", (RStringList "lines", [String "command"]), 112, [],
2627    [], (* XXX needs tests *)
2628    "run a command via the shell returning lines",
2629    "\
2630 This is the same as C<guestfs_sh>, but splits the result
2631 into a list of lines.
2632
2633 See also: C<guestfs_command_lines>");
2634
2635   ("glob_expand", (RStringList "paths", [Pathname "pattern"]), 113, [],
2636    (* Use Pathname here, and hence ABS_PATH (pattern,... in generated
2637     * code in stubs.c, since all valid glob patterns must start with "/".
2638     * There is no concept of "cwd" in libguestfs, hence no "."-relative names.
2639     *)
2640    [InitBasicFS, Always, TestOutputList (
2641       [["mkdir_p"; "/a/b/c"];
2642        ["touch"; "/a/b/c/d"];
2643        ["touch"; "/a/b/c/e"];
2644        ["glob_expand"; "/a/b/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2645     InitBasicFS, Always, TestOutputList (
2646       [["mkdir_p"; "/a/b/c"];
2647        ["touch"; "/a/b/c/d"];
2648        ["touch"; "/a/b/c/e"];
2649        ["glob_expand"; "/a/*/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2650     InitBasicFS, Always, TestOutputList (
2651       [["mkdir_p"; "/a/b/c"];
2652        ["touch"; "/a/b/c/d"];
2653        ["touch"; "/a/b/c/e"];
2654        ["glob_expand"; "/a/*/x/*"]], [])],
2655    "expand a wildcard path",
2656    "\
2657 This command searches for all the pathnames matching
2658 C<pattern> according to the wildcard expansion rules
2659 used by the shell.
2660
2661 If no paths match, then this returns an empty list
2662 (note: not an error).
2663
2664 It is just a wrapper around the C L<glob(3)> function
2665 with flags C<GLOB_MARK|GLOB_BRACE>.
2666 See that manual page for more details.");
2667
2668   ("scrub_device", (RErr, [Device "device"]), 114, [DangerWillRobinson; Optional "scrub"],
2669    [InitNone, Always, TestRun ( (* use /dev/sdc because it's smaller *)
2670       [["scrub_device"; "/dev/sdc"]])],
2671    "scrub (securely wipe) a device",
2672    "\
2673 This command writes patterns over C<device> to make data retrieval
2674 more difficult.
2675
2676 It is an interface to the L<scrub(1)> program.  See that
2677 manual page for more details.");
2678
2679   ("scrub_file", (RErr, [Pathname "file"]), 115, [Optional "scrub"],
2680    [InitBasicFS, Always, TestRun (
2681       [["write_file"; "/file"; "content"; "0"];
2682        ["scrub_file"; "/file"]])],
2683    "scrub (securely wipe) a file",
2684    "\
2685 This command writes patterns over a file to make data retrieval
2686 more difficult.
2687
2688 The file is I<removed> after scrubbing.
2689
2690 It is an interface to the L<scrub(1)> program.  See that
2691 manual page for more details.");
2692
2693   ("scrub_freespace", (RErr, [Pathname "dir"]), 116, [Optional "scrub"],
2694    [], (* XXX needs testing *)
2695    "scrub (securely wipe) free space",
2696    "\
2697 This command creates the directory C<dir> and then fills it
2698 with files until the filesystem is full, and scrubs the files
2699 as for C<guestfs_scrub_file>, and deletes them.
2700 The intention is to scrub any free space on the partition
2701 containing C<dir>.
2702
2703 It is an interface to the L<scrub(1)> program.  See that
2704 manual page for more details.");
2705
2706   ("mkdtemp", (RString "dir", [Pathname "template"]), 117, [],
2707    [InitBasicFS, Always, TestRun (
2708       [["mkdir"; "/tmp"];
2709        ["mkdtemp"; "/tmp/tmpXXXXXX"]])],
2710    "create a temporary directory",
2711    "\
2712 This command creates a temporary directory.  The
2713 C<template> parameter should be a full pathname for the
2714 temporary directory name with the final six characters being
2715 \"XXXXXX\".
2716
2717 For example: \"/tmp/myprogXXXXXX\" or \"/Temp/myprogXXXXXX\",
2718 the second one being suitable for Windows filesystems.
2719
2720 The name of the temporary directory that was created
2721 is returned.
2722
2723 The temporary directory is created with mode 0700
2724 and is owned by root.
2725
2726 The caller is responsible for deleting the temporary
2727 directory and its contents after use.
2728
2729 See also: L<mkdtemp(3)>");
2730
2731   ("wc_l", (RInt "lines", [Pathname "path"]), 118, [],
2732    [InitISOFS, Always, TestOutputInt (
2733       [["wc_l"; "/10klines"]], 10000)],
2734    "count lines in a file",
2735    "\
2736 This command counts the lines in a file, using the
2737 C<wc -l> external command.");
2738
2739   ("wc_w", (RInt "words", [Pathname "path"]), 119, [],
2740    [InitISOFS, Always, TestOutputInt (
2741       [["wc_w"; "/10klines"]], 10000)],
2742    "count words in a file",
2743    "\
2744 This command counts the words in a file, using the
2745 C<wc -w> external command.");
2746
2747   ("wc_c", (RInt "chars", [Pathname "path"]), 120, [],
2748    [InitISOFS, Always, TestOutputInt (
2749       [["wc_c"; "/100kallspaces"]], 102400)],
2750    "count characters in a file",
2751    "\
2752 This command counts the characters in a file, using the
2753 C<wc -c> external command.");
2754
2755   ("head", (RStringList "lines", [Pathname "path"]), 121, [ProtocolLimitWarning],
2756    [InitISOFS, Always, TestOutputList (
2757       [["head"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"])],
2758    "return first 10 lines of a file",
2759    "\
2760 This command returns up to the first 10 lines of a file as
2761 a list of strings.");
2762
2763   ("head_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 122, [ProtocolLimitWarning],
2764    [InitISOFS, Always, TestOutputList (
2765       [["head_n"; "3"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2766     InitISOFS, Always, TestOutputList (
2767       [["head_n"; "-9997"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2768     InitISOFS, Always, TestOutputList (
2769       [["head_n"; "0"; "/10klines"]], [])],
2770    "return first N lines of a file",
2771    "\
2772 If the parameter C<nrlines> is a positive number, this returns the first
2773 C<nrlines> lines of the file C<path>.
2774
2775 If the parameter C<nrlines> is a negative number, this returns lines
2776 from the file C<path>, excluding the last C<nrlines> lines.
2777
2778 If the parameter C<nrlines> is zero, this returns an empty list.");
2779
2780   ("tail", (RStringList "lines", [Pathname "path"]), 123, [ProtocolLimitWarning],
2781    [InitISOFS, Always, TestOutputList (
2782       [["tail"; "/10klines"]], ["9990abcdefghijklmnopqrstuvwxyz";"9991abcdefghijklmnopqrstuvwxyz";"9992abcdefghijklmnopqrstuvwxyz";"9993abcdefghijklmnopqrstuvwxyz";"9994abcdefghijklmnopqrstuvwxyz";"9995abcdefghijklmnopqrstuvwxyz";"9996abcdefghijklmnopqrstuvwxyz";"9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"])],
2783    "return last 10 lines of a file",
2784    "\
2785 This command returns up to the last 10 lines of a file as
2786 a list of strings.");
2787
2788   ("tail_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 124, [ProtocolLimitWarning],
2789    [InitISOFS, Always, TestOutputList (
2790       [["tail_n"; "3"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2791     InitISOFS, Always, TestOutputList (
2792       [["tail_n"; "-9998"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2793     InitISOFS, Always, TestOutputList (
2794       [["tail_n"; "0"; "/10klines"]], [])],
2795    "return last N lines of a file",
2796    "\
2797 If the parameter C<nrlines> is a positive number, this returns the last
2798 C<nrlines> lines of the file C<path>.
2799
2800 If the parameter C<nrlines> is a negative number, this returns lines
2801 from the file C<path>, starting with the C<-nrlines>th line.
2802
2803 If the parameter C<nrlines> is zero, this returns an empty list.");
2804
2805   ("df", (RString "output", []), 125, [],
2806    [], (* XXX Tricky to test because it depends on the exact format
2807         * of the 'df' command and other imponderables.
2808         *)
2809    "report file system disk space usage",
2810    "\
2811 This command runs the C<df> command to report disk space used.
2812
2813 This command is mostly useful for interactive sessions.  It
2814 is I<not> intended that you try to parse the output string.
2815 Use C<statvfs> from programs.");
2816
2817   ("df_h", (RString "output", []), 126, [],
2818    [], (* XXX Tricky to test because it depends on the exact format
2819         * of the 'df' command and other imponderables.
2820         *)
2821    "report file system disk space usage (human readable)",
2822    "\
2823 This command runs the C<df -h> command to report disk space used
2824 in human-readable format.
2825
2826 This command is mostly useful for interactive sessions.  It
2827 is I<not> intended that you try to parse the output string.
2828 Use C<statvfs> from programs.");
2829
2830   ("du", (RInt64 "sizekb", [Pathname "path"]), 127, [],
2831    [InitISOFS, Always, TestOutputInt (
2832       [["du"; "/directory"]], 2 (* ISO fs blocksize is 2K *))],
2833    "estimate file space usage",
2834    "\
2835 This command runs the C<du -s> command to estimate file space
2836 usage for C<path>.
2837
2838 C<path> can be a file or a directory.  If C<path> is a directory
2839 then the estimate includes the contents of the directory and all
2840 subdirectories (recursively).
2841
2842 The result is the estimated size in I<kilobytes>
2843 (ie. units of 1024 bytes).");
2844
2845   ("initrd_list", (RStringList "filenames", [Pathname "path"]), 128, [],
2846    [InitISOFS, Always, TestOutputList (
2847       [["initrd_list"; "/initrd"]], ["empty";"known-1";"known-2";"known-3";"known-4"; "known-5"])],
2848    "list files in an initrd",
2849    "\
2850 This command lists out files contained in an initrd.
2851
2852 The files are listed without any initial C</> character.  The
2853 files are listed in the order they appear (not necessarily
2854 alphabetical).  Directory names are listed as separate items.
2855
2856 Old Linux kernels (2.4 and earlier) used a compressed ext2
2857 filesystem as initrd.  We I<only> support the newer initramfs
2858 format (compressed cpio files).");
2859
2860   ("mount_loop", (RErr, [Pathname "file"; Pathname "mountpoint"]), 129, [],
2861    [],
2862    "mount a file using the loop device",
2863    "\
2864 This command lets you mount C<file> (a filesystem image
2865 in a file) on a mount point.  It is entirely equivalent to
2866 the command C<mount -o loop file mountpoint>.");
2867
2868   ("mkswap", (RErr, [Device "device"]), 130, [],
2869    [InitEmpty, Always, TestRun (
2870       [["part_disk"; "/dev/sda"; "mbr"];
2871        ["mkswap"; "/dev/sda1"]])],
2872    "create a swap partition",
2873    "\
2874 Create a swap partition on C<device>.");
2875
2876   ("mkswap_L", (RErr, [String "label"; Device "device"]), 131, [],
2877    [InitEmpty, Always, TestRun (
2878       [["part_disk"; "/dev/sda"; "mbr"];
2879        ["mkswap_L"; "hello"; "/dev/sda1"]])],
2880    "create a swap partition with a label",
2881    "\
2882 Create a swap partition on C<device> with label C<label>.
2883
2884 Note that you cannot attach a swap label to a block device
2885 (eg. C</dev/sda>), just to a partition.  This appears to be
2886 a limitation of the kernel or swap tools.");
2887
2888   ("mkswap_U", (RErr, [String "uuid"; Device "device"]), 132, [Optional "linuxfsuuid"],
2889    (let uuid = uuidgen () in
2890     [InitEmpty, Always, TestRun (
2891        [["part_disk"; "/dev/sda"; "mbr"];
2892         ["mkswap_U"; uuid; "/dev/sda1"]])]),
2893    "create a swap partition with an explicit UUID",
2894    "\
2895 Create a swap partition on C<device> with UUID C<uuid>.");
2896
2897   ("mknod", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 133, [Optional "mknod"],
2898    [InitBasicFS, Always, TestOutputStruct (
2899       [["mknod"; "0o10777"; "0"; "0"; "/node"];
2900        (* NB: default umask 022 means 0777 -> 0755 in these tests *)
2901        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)]);
2902     InitBasicFS, Always, TestOutputStruct (
2903       [["mknod"; "0o60777"; "66"; "99"; "/node"];
2904        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
2905    "make block, character or FIFO devices",
2906    "\
2907 This call creates block or character special devices, or
2908 named pipes (FIFOs).
2909
2910 The C<mode> parameter should be the mode, using the standard
2911 constants.  C<devmajor> and C<devminor> are the
2912 device major and minor numbers, only used when creating block
2913 and character special devices.");
2914
2915   ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [Optional "mknod"],
2916    [InitBasicFS, Always, TestOutputStruct (
2917       [["mkfifo"; "0o777"; "/node"];
2918        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)])],
2919    "make FIFO (named pipe)",
2920    "\
2921 This call creates a FIFO (named pipe) called C<path> with
2922 mode C<mode>.  It is just a convenient wrapper around
2923 C<guestfs_mknod>.");
2924
2925   ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [Optional "mknod"],
2926    [InitBasicFS, Always, TestOutputStruct (
2927       [["mknod_b"; "0o777"; "99"; "66"; "/node"];
2928        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
2929    "make block device node",
2930    "\
2931 This call creates a block device node called C<path> with
2932 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
2933 It is just a convenient wrapper around C<guestfs_mknod>.");
2934
2935   ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [Optional "mknod"],
2936    [InitBasicFS, Always, TestOutputStruct (
2937       [["mknod_c"; "0o777"; "99"; "66"; "/node"];
2938        ["stat"; "/node"]], [CompareWithInt ("mode", 0o20755)])],
2939    "make char device node",
2940    "\
2941 This call creates a char device node called C<path> with
2942 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
2943 It is just a convenient wrapper around C<guestfs_mknod>.");
2944
2945   ("umask", (RInt "oldmask", [Int "mask"]), 137, [],
2946    [], (* XXX umask is one of those stateful things that we should
2947         * reset between each test.
2948         *)
2949    "set file mode creation mask (umask)",
2950    "\
2951 This function sets the mask used for creating new files and
2952 device nodes to C<mask & 0777>.
2953
2954 Typical umask values would be C<022> which creates new files
2955 with permissions like \"-rw-r--r--\" or \"-rwxr-xr-x\", and
2956 C<002> which creates new files with permissions like
2957 \"-rw-rw-r--\" or \"-rwxrwxr-x\".
2958
2959 The default umask is C<022>.  This is important because it
2960 means that directories and device nodes will be created with
2961 C<0644> or C<0755> mode even if you specify C<0777>.
2962
2963 See also L<umask(2)>, C<guestfs_mknod>, C<guestfs_mkdir>.
2964
2965 This call returns the previous umask.");
2966
2967   ("readdir", (RStructList ("entries", "dirent"), [Pathname "dir"]), 138, [],
2968    [],
2969    "read directories entries",
2970    "\
2971 This returns the list of directory entries in directory C<dir>.
2972
2973 All entries in the directory are returned, including C<.> and
2974 C<..>.  The entries are I<not> sorted, but returned in the same
2975 order as the underlying filesystem.
2976
2977 Also this call returns basic file type information about each
2978 file.  The C<ftyp> field will contain one of the following characters:
2979
2980 =over 4
2981
2982 =item 'b'
2983
2984 Block special
2985
2986 =item 'c'
2987
2988 Char special
2989
2990 =item 'd'
2991
2992 Directory
2993
2994 =item 'f'
2995
2996 FIFO (named pipe)
2997
2998 =item 'l'
2999
3000 Symbolic link
3001
3002 =item 'r'
3003
3004 Regular file
3005
3006 =item 's'
3007
3008 Socket
3009
3010 =item 'u'
3011
3012 Unknown file type
3013
3014 =item '?'
3015
3016 The L<readdir(3)> returned a C<d_type> field with an
3017 unexpected value
3018
3019 =back
3020
3021 This function is primarily intended for use by programs.  To
3022 get a simple list of names, use C<guestfs_ls>.  To get a printable
3023 directory for human consumption, use C<guestfs_ll>.");
3024
3025   ("sfdiskM", (RErr, [Device "device"; StringList "lines"]), 139, [DangerWillRobinson],
3026    [],
3027    "create partitions on a block device",
3028    "\
3029 This is a simplified interface to the C<guestfs_sfdisk>
3030 command, where partition sizes are specified in megabytes
3031 only (rounded to the nearest cylinder) and you don't need
3032 to specify the cyls, heads and sectors parameters which
3033 were rarely if ever used anyway.
3034
3035 See also: C<guestfs_sfdisk>, the L<sfdisk(8)> manpage
3036 and C<guestfs_part_disk>");
3037
3038   ("zfile", (RString "description", [String "meth"; Pathname "path"]), 140, [DeprecatedBy "file"],
3039    [],
3040    "determine file type inside a compressed file",
3041    "\
3042 This command runs C<file> after first decompressing C<path>
3043 using C<method>.
3044
3045 C<method> must be one of C<gzip>, C<compress> or C<bzip2>.
3046
3047 Since 1.0.63, use C<guestfs_file> instead which can now
3048 process compressed files.");
3049
3050   ("getxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 141, [Optional "linuxxattrs"],
3051    [],
3052    "list extended attributes of a file or directory",
3053    "\
3054 This call lists the extended attributes of the file or directory
3055 C<path>.
3056
3057 At the system call level, this is a combination of the
3058 L<listxattr(2)> and L<getxattr(2)> calls.
3059
3060 See also: C<guestfs_lgetxattrs>, L<attr(5)>.");
3061
3062   ("lgetxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 142, [Optional "linuxxattrs"],
3063    [],
3064    "list extended attributes of a file or directory",
3065    "\
3066 This is the same as C<guestfs_getxattrs>, but if C<path>
3067 is a symbolic link, then it returns the extended attributes
3068 of the link itself.");
3069
3070   ("setxattr", (RErr, [String "xattr";
3071                        String "val"; Int "vallen"; (* will be BufferIn *)
3072                        Pathname "path"]), 143, [Optional "linuxxattrs"],
3073    [],
3074    "set extended attribute of a file or directory",
3075    "\
3076 This call sets the extended attribute named C<xattr>
3077 of the file C<path> to the value C<val> (of length C<vallen>).
3078 The value is arbitrary 8 bit data.
3079
3080 See also: C<guestfs_lsetxattr>, L<attr(5)>.");
3081
3082   ("lsetxattr", (RErr, [String "xattr";
3083                         String "val"; Int "vallen"; (* will be BufferIn *)
3084                         Pathname "path"]), 144, [Optional "linuxxattrs"],
3085    [],
3086    "set extended attribute of a file or directory",
3087    "\
3088 This is the same as C<guestfs_setxattr>, but if C<path>
3089 is a symbolic link, then it sets an extended attribute
3090 of the link itself.");
3091
3092   ("removexattr", (RErr, [String "xattr"; Pathname "path"]), 145, [Optional "linuxxattrs"],
3093    [],
3094    "remove extended attribute of a file or directory",
3095    "\
3096 This call removes the extended attribute named C<xattr>
3097 of the file C<path>.
3098
3099 See also: C<guestfs_lremovexattr>, L<attr(5)>.");
3100
3101   ("lremovexattr", (RErr, [String "xattr"; Pathname "path"]), 146, [Optional "linuxxattrs"],
3102    [],
3103    "remove extended attribute of a file or directory",
3104    "\
3105 This is the same as C<guestfs_removexattr>, but if C<path>
3106 is a symbolic link, then it removes an extended attribute
3107 of the link itself.");
3108
3109   ("mountpoints", (RHashtable "mps", []), 147, [],
3110    [],
3111    "show mountpoints",
3112    "\
3113 This call is similar to C<guestfs_mounts>.  That call returns
3114 a list of devices.  This one returns a hash table (map) of
3115 device name to directory where the device is mounted.");
3116
3117   ("mkmountpoint", (RErr, [String "exemptpath"]), 148, [],
3118   (* This is a special case: while you would expect a parameter
3119    * of type "Pathname", that doesn't work, because it implies
3120    * NEED_ROOT in the generated calling code in stubs.c, and
3121    * this function cannot use NEED_ROOT.
3122    *)
3123    [],
3124    "create a mountpoint",
3125    "\
3126 C<guestfs_mkmountpoint> and C<guestfs_rmmountpoint> are
3127 specialized calls that can be used to create extra mountpoints
3128 before mounting the first filesystem.
3129
3130 These calls are I<only> necessary in some very limited circumstances,
3131 mainly the case where you want to mount a mix of unrelated and/or
3132 read-only filesystems together.
3133
3134 For example, live CDs often contain a \"Russian doll\" nest of
3135 filesystems, an ISO outer layer, with a squashfs image inside, with
3136 an ext2/3 image inside that.  You can unpack this as follows
3137 in guestfish:
3138
3139  add-ro Fedora-11-i686-Live.iso
3140  run
3141  mkmountpoint /cd
3142  mkmountpoint /squash
3143  mkmountpoint /ext3
3144  mount /dev/sda /cd
3145  mount-loop /cd/LiveOS/squashfs.img /squash
3146  mount-loop /squash/LiveOS/ext3fs.img /ext3
3147
3148 The inner filesystem is now unpacked under the /ext3 mountpoint.");
3149
3150   ("rmmountpoint", (RErr, [String "exemptpath"]), 149, [],
3151    [],
3152    "remove a mountpoint",
3153    "\
3154 This calls removes a mountpoint that was previously created
3155 with C<guestfs_mkmountpoint>.  See C<guestfs_mkmountpoint>
3156 for full details.");
3157
3158   ("read_file", (RBufferOut "content", [Pathname "path"]), 150, [ProtocolLimitWarning],
3159    [InitISOFS, Always, TestOutputBuffer (
3160       [["read_file"; "/known-4"]], "abc\ndef\nghi")],
3161    "read a file",
3162    "\
3163 This calls returns the contents of the file C<path> as a
3164 buffer.
3165
3166 Unlike C<guestfs_cat>, this function can correctly
3167 handle files that contain embedded ASCII NUL characters.
3168 However unlike C<guestfs_download>, this function is limited
3169 in the total size of file that can be handled.");
3170
3171   ("grep", (RStringList "lines", [String "regex"; Pathname "path"]), 151, [ProtocolLimitWarning],
3172    [InitISOFS, Always, TestOutputList (
3173       [["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]);
3174     InitISOFS, Always, TestOutputList (
3175       [["grep"; "nomatch"; "/test-grep.txt"]], [])],
3176    "return lines matching a pattern",
3177    "\
3178 This calls the external C<grep> program and returns the
3179 matching lines.");
3180
3181   ("egrep", (RStringList "lines", [String "regex"; Pathname "path"]), 152, [ProtocolLimitWarning],
3182    [InitISOFS, Always, TestOutputList (
3183       [["egrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3184    "return lines matching a pattern",
3185    "\
3186 This calls the external C<egrep> program and returns the
3187 matching lines.");
3188
3189   ("fgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 153, [ProtocolLimitWarning],
3190    [InitISOFS, Always, TestOutputList (
3191       [["fgrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3192    "return lines matching a pattern",
3193    "\
3194 This calls the external C<fgrep> program and returns the
3195 matching lines.");
3196
3197   ("grepi", (RStringList "lines", [String "regex"; Pathname "path"]), 154, [ProtocolLimitWarning],
3198    [InitISOFS, Always, TestOutputList (
3199       [["grepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3200    "return lines matching a pattern",
3201    "\
3202 This calls the external C<grep -i> program and returns the
3203 matching lines.");
3204
3205   ("egrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 155, [ProtocolLimitWarning],
3206    [InitISOFS, Always, TestOutputList (
3207       [["egrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3208    "return lines matching a pattern",
3209    "\
3210 This calls the external C<egrep -i> program and returns the
3211 matching lines.");
3212
3213   ("fgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 156, [ProtocolLimitWarning],
3214    [InitISOFS, Always, TestOutputList (
3215       [["fgrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3216    "return lines matching a pattern",
3217    "\
3218 This calls the external C<fgrep -i> program and returns the
3219 matching lines.");
3220
3221   ("zgrep", (RStringList "lines", [String "regex"; Pathname "path"]), 157, [ProtocolLimitWarning],
3222    [InitISOFS, Always, TestOutputList (
3223       [["zgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3224    "return lines matching a pattern",
3225    "\
3226 This calls the external C<zgrep> program and returns the
3227 matching lines.");
3228
3229   ("zegrep", (RStringList "lines", [String "regex"; Pathname "path"]), 158, [ProtocolLimitWarning],
3230    [InitISOFS, Always, TestOutputList (
3231       [["zegrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3232    "return lines matching a pattern",
3233    "\
3234 This calls the external C<zegrep> program and returns the
3235 matching lines.");
3236
3237   ("zfgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 159, [ProtocolLimitWarning],
3238    [InitISOFS, Always, TestOutputList (
3239       [["zfgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3240    "return lines matching a pattern",
3241    "\
3242 This calls the external C<zfgrep> program and returns the
3243 matching lines.");
3244
3245   ("zgrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 160, [ProtocolLimitWarning],
3246    [InitISOFS, Always, TestOutputList (
3247       [["zgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3248    "return lines matching a pattern",
3249    "\
3250 This calls the external C<zgrep -i> program and returns the
3251 matching lines.");
3252
3253   ("zegrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 161, [ProtocolLimitWarning],
3254    [InitISOFS, Always, TestOutputList (
3255       [["zegrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3256    "return lines matching a pattern",
3257    "\
3258 This calls the external C<zegrep -i> program and returns the
3259 matching lines.");
3260
3261   ("zfgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 162, [ProtocolLimitWarning],
3262    [InitISOFS, Always, TestOutputList (
3263       [["zfgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3264    "return lines matching a pattern",
3265    "\
3266 This calls the external C<zfgrep -i> program and returns the
3267 matching lines.");
3268
3269   ("realpath", (RString "rpath", [Pathname "path"]), 163, [],
3270    [InitISOFS, Always, TestOutput (
3271       [["realpath"; "/../directory"]], "/directory")],
3272    "canonicalized absolute pathname",
3273    "\
3274 Return the canonicalized absolute pathname of C<path>.  The
3275 returned path has no C<.>, C<..> or symbolic link path elements.");
3276
3277   ("ln", (RErr, [String "target"; Pathname "linkname"]), 164, [],
3278    [InitBasicFS, Always, TestOutputStruct (
3279       [["touch"; "/a"];
3280        ["ln"; "/a"; "/b"];
3281        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3282    "create a hard link",
3283    "\
3284 This command creates a hard link using the C<ln> command.");
3285
3286   ("ln_f", (RErr, [String "target"; Pathname "linkname"]), 165, [],
3287    [InitBasicFS, Always, TestOutputStruct (
3288       [["touch"; "/a"];
3289        ["touch"; "/b"];
3290        ["ln_f"; "/a"; "/b"];
3291        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3292    "create a hard link",
3293    "\
3294 This command creates a hard link using the C<ln -f> command.
3295 The C<-f> option removes the link (C<linkname>) if it exists already.");
3296
3297   ("ln_s", (RErr, [String "target"; Pathname "linkname"]), 166, [],
3298    [InitBasicFS, Always, TestOutputStruct (
3299       [["touch"; "/a"];
3300        ["ln_s"; "a"; "/b"];
3301        ["lstat"; "/b"]], [CompareWithInt ("mode", 0o120777)])],
3302    "create a symbolic link",
3303    "\
3304 This command creates a symbolic link using the C<ln -s> command.");
3305
3306   ("ln_sf", (RErr, [String "target"; Pathname "linkname"]), 167, [],
3307    [InitBasicFS, Always, TestOutput (
3308       [["mkdir_p"; "/a/b"];
3309        ["touch"; "/a/b/c"];
3310        ["ln_sf"; "../d"; "/a/b/c"];
3311        ["readlink"; "/a/b/c"]], "../d")],
3312    "create a symbolic link",
3313    "\
3314 This command creates a symbolic link using the C<ln -sf> command,
3315 The C<-f> option removes the link (C<linkname>) if it exists already.");
3316
3317   ("readlink", (RString "link", [Pathname "path"]), 168, [],
3318    [] (* XXX tested above *),
3319    "read the target of a symbolic link",
3320    "\
3321 This command reads the target of a symbolic link.");
3322
3323   ("fallocate", (RErr, [Pathname "path"; Int "len"]), 169, [],
3324    [InitBasicFS, Always, TestOutputStruct (
3325       [["fallocate"; "/a"; "1000000"];
3326        ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
3327    "preallocate a file in the guest filesystem",
3328    "\
3329 This command preallocates a file (containing zero bytes) named
3330 C<path> of size C<len> bytes.  If the file exists already, it
3331 is overwritten.
3332
3333 Do not confuse this with the guestfish-specific
3334 C<alloc> command which allocates a file in the host and
3335 attaches it as a device.");
3336
3337   ("swapon_device", (RErr, [Device "device"]), 170, [],
3338    [InitPartition, Always, TestRun (
3339       [["mkswap"; "/dev/sda1"];
3340        ["swapon_device"; "/dev/sda1"];
3341        ["swapoff_device"; "/dev/sda1"]])],
3342    "enable swap on device",
3343    "\
3344 This command enables the libguestfs appliance to use the
3345 swap device or partition named C<device>.  The increased
3346 memory is made available for all commands, for example
3347 those run using C<guestfs_command> or C<guestfs_sh>.
3348
3349 Note that you should not swap to existing guest swap
3350 partitions unless you know what you are doing.  They may
3351 contain hibernation information, or other information that
3352 the guest doesn't want you to trash.  You also risk leaking
3353 information about the host to the guest this way.  Instead,
3354 attach a new host device to the guest and swap on that.");
3355
3356   ("swapoff_device", (RErr, [Device "device"]), 171, [],
3357    [], (* XXX tested by swapon_device *)
3358    "disable swap on device",
3359    "\
3360 This command disables the libguestfs appliance swap
3361 device or partition named C<device>.
3362 See C<guestfs_swapon_device>.");
3363
3364   ("swapon_file", (RErr, [Pathname "file"]), 172, [],
3365    [InitBasicFS, Always, TestRun (
3366       [["fallocate"; "/swap"; "8388608"];
3367        ["mkswap_file"; "/swap"];
3368        ["swapon_file"; "/swap"];
3369        ["swapoff_file"; "/swap"]])],
3370    "enable swap on file",
3371    "\
3372 This command enables swap to a file.
3373 See C<guestfs_swapon_device> for other notes.");
3374
3375   ("swapoff_file", (RErr, [Pathname "file"]), 173, [],
3376    [], (* XXX tested by swapon_file *)
3377    "disable swap on file",
3378    "\
3379 This command disables the libguestfs appliance swap on file.");
3380
3381   ("swapon_label", (RErr, [String "label"]), 174, [],
3382    [InitEmpty, Always, TestRun (
3383       [["part_disk"; "/dev/sdb"; "mbr"];
3384        ["mkswap_L"; "swapit"; "/dev/sdb1"];
3385        ["swapon_label"; "swapit"];
3386        ["swapoff_label"; "swapit"];
3387        ["zero"; "/dev/sdb"];
3388        ["blockdev_rereadpt"; "/dev/sdb"]])],
3389    "enable swap on labeled swap partition",
3390    "\
3391 This command enables swap to a labeled swap partition.
3392 See C<guestfs_swapon_device> for other notes.");
3393
3394   ("swapoff_label", (RErr, [String "label"]), 175, [],
3395    [], (* XXX tested by swapon_label *)
3396    "disable swap on labeled swap partition",
3397    "\
3398 This command disables the libguestfs appliance swap on
3399 labeled swap partition.");
3400
3401   ("swapon_uuid", (RErr, [String "uuid"]), 176, [Optional "linuxfsuuid"],
3402    (let uuid = uuidgen () in
3403     [InitEmpty, Always, TestRun (
3404        [["mkswap_U"; uuid; "/dev/sdb"];
3405         ["swapon_uuid"; uuid];
3406         ["swapoff_uuid"; uuid]])]),
3407    "enable swap on swap partition by UUID",
3408    "\
3409 This command enables swap to a swap partition with the given UUID.
3410 See C<guestfs_swapon_device> for other notes.");
3411
3412   ("swapoff_uuid", (RErr, [String "uuid"]), 177, [Optional "linuxfsuuid"],
3413    [], (* XXX tested by swapon_uuid *)
3414    "disable swap on swap partition by UUID",
3415    "\
3416 This command disables the libguestfs appliance swap partition
3417 with the given UUID.");
3418
3419   ("mkswap_file", (RErr, [Pathname "path"]), 178, [],
3420    [InitBasicFS, Always, TestRun (
3421       [["fallocate"; "/swap"; "8388608"];
3422        ["mkswap_file"; "/swap"]])],
3423    "create a swap file",
3424    "\
3425 Create a swap file.
3426
3427 This command just writes a swap file signature to an existing
3428 file.  To create the file itself, use something like C<guestfs_fallocate>.");
3429
3430   ("inotify_init", (RErr, [Int "maxevents"]), 179, [Optional "inotify"],
3431    [InitISOFS, Always, TestRun (
3432       [["inotify_init"; "0"]])],
3433    "create an inotify handle",
3434    "\
3435 This command creates a new inotify handle.
3436 The inotify subsystem can be used to notify events which happen to
3437 objects in the guest filesystem.
3438
3439 C<maxevents> is the maximum number of events which will be
3440 queued up between calls to C<guestfs_inotify_read> or
3441 C<guestfs_inotify_files>.
3442 If this is passed as C<0>, then the kernel (or previously set)
3443 default is used.  For Linux 2.6.29 the default was 16384 events.
3444 Beyond this limit, the kernel throws away events, but records
3445 the fact that it threw them away by setting a flag
3446 C<IN_Q_OVERFLOW> in the returned structure list (see
3447 C<guestfs_inotify_read>).
3448
3449 Before any events are generated, you have to add some
3450 watches to the internal watch list.  See:
3451 C<guestfs_inotify_add_watch>,
3452 C<guestfs_inotify_rm_watch> and
3453 C<guestfs_inotify_watch_all>.
3454
3455 Queued up events should be read periodically by calling
3456 C<guestfs_inotify_read>
3457 (or C<guestfs_inotify_files> which is just a helpful
3458 wrapper around C<guestfs_inotify_read>).  If you don't
3459 read the events out often enough then you risk the internal
3460 queue overflowing.
3461
3462 The handle should be closed after use by calling
3463 C<guestfs_inotify_close>.  This also removes any
3464 watches automatically.
3465
3466 See also L<inotify(7)> for an overview of the inotify interface
3467 as exposed by the Linux kernel, which is roughly what we expose
3468 via libguestfs.  Note that there is one global inotify handle
3469 per libguestfs instance.");
3470
3471   ("inotify_add_watch", (RInt64 "wd", [Pathname "path"; Int "mask"]), 180, [Optional "inotify"],
3472    [InitBasicFS, Always, TestOutputList (
3473       [["inotify_init"; "0"];
3474        ["inotify_add_watch"; "/"; "1073741823"];
3475        ["touch"; "/a"];
3476        ["touch"; "/b"];
3477        ["inotify_files"]], ["a"; "b"])],
3478    "add an inotify watch",
3479    "\
3480 Watch C<path> for the events listed in C<mask>.
3481
3482 Note that if C<path> is a directory then events within that
3483 directory are watched, but this does I<not> happen recursively
3484 (in subdirectories).
3485
3486 Note for non-C or non-Linux callers: the inotify events are
3487 defined by the Linux kernel ABI and are listed in
3488 C</usr/include/sys/inotify.h>.");
3489
3490   ("inotify_rm_watch", (RErr, [Int(*XXX64*) "wd"]), 181, [Optional "inotify"],
3491    [],
3492    "remove an inotify watch",
3493    "\
3494 Remove a previously defined inotify watch.
3495 See C<guestfs_inotify_add_watch>.");
3496
3497   ("inotify_read", (RStructList ("events", "inotify_event"), []), 182, [Optional "inotify"],
3498    [],
3499    "return list of inotify events",
3500    "\
3501 Return the complete queue of events that have happened
3502 since the previous read call.
3503
3504 If no events have happened, this returns an empty list.
3505
3506 I<Note>: In order to make sure that all events have been
3507 read, you must call this function repeatedly until it
3508 returns an empty list.  The reason is that the call will
3509 read events up to the maximum appliance-to-host message
3510 size and leave remaining events in the queue.");
3511
3512   ("inotify_files", (RStringList "paths", []), 183, [Optional "inotify"],
3513    [],
3514    "return list of watched files that had events",
3515    "\
3516 This function is a helpful wrapper around C<guestfs_inotify_read>
3517 which just returns a list of pathnames of objects that were
3518 touched.  The returned pathnames are sorted and deduplicated.");
3519
3520   ("inotify_close", (RErr, []), 184, [Optional "inotify"],
3521    [],
3522    "close the inotify handle",
3523    "\
3524 This closes the inotify handle which was previously
3525 opened by inotify_init.  It removes all watches, throws
3526 away any pending events, and deallocates all resources.");
3527
3528   ("setcon", (RErr, [String "context"]), 185, [Optional "selinux"],
3529    [],
3530    "set SELinux security context",
3531    "\
3532 This sets the SELinux security context of the daemon
3533 to the string C<context>.
3534
3535 See the documentation about SELINUX in L<guestfs(3)>.");
3536
3537   ("getcon", (RString "context", []), 186, [Optional "selinux"],
3538    [],
3539    "get SELinux security context",
3540    "\
3541 This gets the SELinux security context of the daemon.
3542
3543 See the documentation about SELINUX in L<guestfs(3)>,
3544 and C<guestfs_setcon>");
3545
3546   ("mkfs_b", (RErr, [String "fstype"; Int "blocksize"; Device "device"]), 187, [],
3547    [InitEmpty, Always, TestOutput (
3548       [["part_disk"; "/dev/sda"; "mbr"];
3549        ["mkfs_b"; "ext2"; "4096"; "/dev/sda1"];
3550        ["mount"; "/dev/sda1"; "/"];
3551        ["write_file"; "/new"; "new file contents"; "0"];
3552        ["cat"; "/new"]], "new file contents")],
3553    "make a filesystem with block size",
3554    "\
3555 This call is similar to C<guestfs_mkfs>, but it allows you to
3556 control the block size of the resulting filesystem.  Supported
3557 block sizes depend on the filesystem type, but typically they
3558 are C<1024>, C<2048> or C<4096> only.");
3559
3560   ("mke2journal", (RErr, [Int "blocksize"; Device "device"]), 188, [],
3561    [InitEmpty, Always, TestOutput (
3562       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3563        ["mke2journal"; "4096"; "/dev/sda1"];
3564        ["mke2fs_J"; "ext2"; "4096"; "/dev/sda2"; "/dev/sda1"];
3565        ["mount"; "/dev/sda2"; "/"];
3566        ["write_file"; "/new"; "new file contents"; "0"];
3567        ["cat"; "/new"]], "new file contents")],
3568    "make ext2/3/4 external journal",
3569    "\
3570 This creates an ext2 external journal on C<device>.  It is equivalent
3571 to the command:
3572
3573  mke2fs -O journal_dev -b blocksize device");
3574
3575   ("mke2journal_L", (RErr, [Int "blocksize"; String "label"; Device "device"]), 189, [],
3576    [InitEmpty, Always, TestOutput (
3577       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3578        ["mke2journal_L"; "4096"; "JOURNAL"; "/dev/sda1"];
3579        ["mke2fs_JL"; "ext2"; "4096"; "/dev/sda2"; "JOURNAL"];
3580        ["mount"; "/dev/sda2"; "/"];
3581        ["write_file"; "/new"; "new file contents"; "0"];
3582        ["cat"; "/new"]], "new file contents")],
3583    "make ext2/3/4 external journal with label",
3584    "\
3585 This creates an ext2 external journal on C<device> with label C<label>.");
3586
3587   ("mke2journal_U", (RErr, [Int "blocksize"; String "uuid"; Device "device"]), 190, [Optional "linuxfsuuid"],
3588    (let uuid = uuidgen () in
3589     [InitEmpty, Always, TestOutput (
3590        [["sfdiskM"; "/dev/sda"; ",100 ,"];
3591         ["mke2journal_U"; "4096"; uuid; "/dev/sda1"];
3592         ["mke2fs_JU"; "ext2"; "4096"; "/dev/sda2"; uuid];
3593         ["mount"; "/dev/sda2"; "/"];
3594         ["write_file"; "/new"; "new file contents"; "0"];
3595         ["cat"; "/new"]], "new file contents")]),
3596    "make ext2/3/4 external journal with UUID",
3597    "\
3598 This creates an ext2 external journal on C<device> with UUID C<uuid>.");
3599
3600   ("mke2fs_J", (RErr, [String "fstype"; Int "blocksize"; Device "device"; Device "journal"]), 191, [],
3601    [],
3602    "make ext2/3/4 filesystem with external journal",
3603    "\
3604 This creates an ext2/3/4 filesystem on C<device> with
3605 an external journal on C<journal>.  It is equivalent
3606 to the command:
3607
3608  mke2fs -t fstype -b blocksize -J device=<journal> <device>
3609
3610 See also C<guestfs_mke2journal>.");
3611
3612   ("mke2fs_JL", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "label"]), 192, [],
3613    [],
3614    "make ext2/3/4 filesystem with external journal",
3615    "\
3616 This creates an ext2/3/4 filesystem on C<device> with
3617 an external journal on the journal labeled C<label>.
3618
3619 See also C<guestfs_mke2journal_L>.");
3620
3621   ("mke2fs_JU", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "uuid"]), 193, [Optional "linuxfsuuid"],
3622    [],
3623    "make ext2/3/4 filesystem with external journal",
3624    "\
3625 This creates an ext2/3/4 filesystem on C<device> with
3626 an external journal on the journal with UUID C<uuid>.
3627
3628 See also C<guestfs_mke2journal_U>.");
3629
3630   ("modprobe", (RErr, [String "modulename"]), 194, [Optional "linuxmodules"],
3631    [InitNone, Always, TestRun [["modprobe"; "fat"]]],
3632    "load a kernel module",
3633    "\
3634 This loads a kernel module in the appliance.
3635
3636 The kernel module must have been whitelisted when libguestfs
3637 was built (see C<appliance/kmod.whitelist.in> in the source).");
3638
3639   ("echo_daemon", (RString "output", [StringList "words"]), 195, [],
3640    [InitNone, Always, TestOutput (
3641      [["echo_daemon"; "This is a test"]], "This is a test"
3642    )],
3643    "echo arguments back to the client",
3644    "\
3645 This command concatenate the list of C<words> passed with single spaces between
3646 them and returns the resulting string.
3647
3648 You can use this command to test the connection through to the daemon.
3649
3650 See also C<guestfs_ping_daemon>.");
3651
3652   ("find0", (RErr, [Pathname "directory"; FileOut "files"]), 196, [],
3653    [], (* There is a regression test for this. *)
3654    "find all files and directories, returning NUL-separated list",
3655    "\
3656 This command lists out all files and directories, recursively,
3657 starting at C<directory>, placing the resulting list in the
3658 external file called C<files>.
3659
3660 This command works the same way as C<guestfs_find> with the
3661 following exceptions:
3662
3663 =over 4
3664
3665 =item *
3666
3667 The resulting list is written to an external file.
3668
3669 =item *
3670
3671 Items (filenames) in the result are separated
3672 by C<\\0> characters.  See L<find(1)> option I<-print0>.
3673
3674 =item *
3675
3676 This command is not limited in the number of names that it
3677 can return.
3678
3679 =item *
3680
3681 The result list is not sorted.
3682
3683 =back");
3684
3685   ("case_sensitive_path", (RString "rpath", [Pathname "path"]), 197, [],
3686    [InitISOFS, Always, TestOutput (
3687       [["case_sensitive_path"; "/DIRECTORY"]], "/directory");
3688     InitISOFS, Always, TestOutput (
3689       [["case_sensitive_path"; "/DIRECTORY/"]], "/directory");
3690     InitISOFS, Always, TestOutput (
3691       [["case_sensitive_path"; "/Known-1"]], "/known-1");
3692     InitISOFS, Always, TestLastFail (
3693       [["case_sensitive_path"; "/Known-1/"]]);
3694     InitBasicFS, Always, TestOutput (
3695       [["mkdir"; "/a"];
3696        ["mkdir"; "/a/bbb"];
3697        ["touch"; "/a/bbb/c"];
3698        ["case_sensitive_path"; "/A/bbB/C"]], "/a/bbb/c");
3699     InitBasicFS, Always, TestOutput (
3700       [["mkdir"; "/a"];
3701        ["mkdir"; "/a/bbb"];
3702        ["touch"; "/a/bbb/c"];
3703        ["case_sensitive_path"; "/A////bbB/C"]], "/a/bbb/c");
3704     InitBasicFS, Always, TestLastFail (
3705       [["mkdir"; "/a"];
3706        ["mkdir"; "/a/bbb"];
3707        ["touch"; "/a/bbb/c"];
3708        ["case_sensitive_path"; "/A/bbb/../bbb/C"]])],
3709    "return true path on case-insensitive filesystem",
3710    "\
3711 This can be used to resolve case insensitive paths on
3712 a filesystem which is case sensitive.  The use case is
3713 to resolve paths which you have read from Windows configuration
3714 files or the Windows Registry, to the true path.
3715
3716 The command handles a peculiarity of the Linux ntfs-3g
3717 filesystem driver (and probably others), which is that although
3718 the underlying filesystem is case-insensitive, the driver
3719 exports the filesystem to Linux as case-sensitive.
3720
3721 One consequence of this is that special directories such
3722 as C<c:\\windows> may appear as C</WINDOWS> or C</windows>
3723 (or other things) depending on the precise details of how
3724 they were created.  In Windows itself this would not be
3725 a problem.
3726
3727 Bug or feature?  You decide:
3728 L<http://www.tuxera.com/community/ntfs-3g-faq/#posixfilenames1>
3729
3730 This function resolves the true case of each element in the
3731 path and returns the case-sensitive path.
3732
3733 Thus C<guestfs_case_sensitive_path> (\"/Windows/System32\")
3734 might return C<\"/WINDOWS/system32\"> (the exact return value
3735 would depend on details of how the directories were originally
3736 created under Windows).
3737
3738 I<Note>:
3739 This function does not handle drive names, backslashes etc.
3740
3741 See also C<guestfs_realpath>.");
3742
3743   ("vfs_type", (RString "fstype", [Device "device"]), 198, [],
3744    [InitBasicFS, Always, TestOutput (
3745       [["vfs_type"; "/dev/sda1"]], "ext2")],
3746    "get the Linux VFS type corresponding to a mounted device",
3747    "\
3748 This command gets the block device type corresponding to
3749 a mounted device called C<device>.
3750
3751 Usually the result is the name of the Linux VFS module that
3752 is used to mount this device (probably determined automatically
3753 if you used the C<guestfs_mount> call).");
3754
3755   ("truncate", (RErr, [Pathname "path"]), 199, [],
3756    [InitBasicFS, Always, TestOutputStruct (
3757       [["write_file"; "/test"; "some stuff so size is not zero"; "0"];
3758        ["truncate"; "/test"];
3759        ["stat"; "/test"]], [CompareWithInt ("size", 0)])],
3760    "truncate a file to zero size",
3761    "\
3762 This command truncates C<path> to a zero-length file.  The
3763 file must exist already.");
3764
3765   ("truncate_size", (RErr, [Pathname "path"; Int64 "size"]), 200, [],
3766    [InitBasicFS, Always, TestOutputStruct (
3767       [["touch"; "/test"];
3768        ["truncate_size"; "/test"; "1000"];
3769        ["stat"; "/test"]], [CompareWithInt ("size", 1000)])],
3770    "truncate a file to a particular size",
3771    "\
3772 This command truncates C<path> to size C<size> bytes.  The file
3773 must exist already.  If the file is smaller than C<size> then
3774 the file is extended to the required size with null bytes.");
3775
3776   ("utimens", (RErr, [Pathname "path"; Int64 "atsecs"; Int64 "atnsecs"; Int64 "mtsecs"; Int64 "mtnsecs"]), 201, [],
3777    [InitBasicFS, Always, TestOutputStruct (
3778       [["touch"; "/test"];
3779        ["utimens"; "/test"; "12345"; "67890"; "9876"; "5432"];
3780        ["stat"; "/test"]], [CompareWithInt ("mtime", 9876)])],
3781    "set timestamp of a file with nanosecond precision",
3782    "\
3783 This command sets the timestamps of a file with nanosecond
3784 precision.
3785
3786 C<atsecs, atnsecs> are the last access time (atime) in secs and
3787 nanoseconds from the epoch.
3788
3789 C<mtsecs, mtnsecs> are the last modification time (mtime) in
3790 secs and nanoseconds from the epoch.
3791
3792 If the C<*nsecs> field contains the special value C<-1> then
3793 the corresponding timestamp is set to the current time.  (The
3794 C<*secs> field is ignored in this case).
3795
3796 If the C<*nsecs> field contains the special value C<-2> then
3797 the corresponding timestamp is left unchanged.  (The
3798 C<*secs> field is ignored in this case).");
3799
3800   ("mkdir_mode", (RErr, [Pathname "path"; Int "mode"]), 202, [],
3801    [InitBasicFS, Always, TestOutputStruct (
3802       [["mkdir_mode"; "/test"; "0o111"];
3803        ["stat"; "/test"]], [CompareWithInt ("mode", 0o40111)])],
3804    "create a directory with a particular mode",
3805    "\
3806 This command creates a directory, setting the initial permissions
3807 of the directory to C<mode>.  See also C<guestfs_mkdir>.");
3808
3809   ("lchown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 203, [],
3810    [], (* XXX *)
3811    "change file owner and group",
3812    "\
3813 Change the file owner to C<owner> and group to C<group>.
3814 This is like C<guestfs_chown> but if C<path> is a symlink then
3815 the link itself is changed, not the target.
3816
3817 Only numeric uid and gid are supported.  If you want to use
3818 names, you will need to locate and parse the password file
3819 yourself (Augeas support makes this relatively easy).");
3820
3821   ("lstatlist", (RStructList ("statbufs", "stat"), [Pathname "path"; StringList "names"]), 204, [],
3822    [], (* XXX *)
3823    "lstat on multiple files",
3824    "\
3825 This call allows you to perform the C<guestfs_lstat> operation
3826 on multiple files, where all files are in the directory C<path>.
3827 C<names> is the list of files from this directory.
3828
3829 On return you get a list of stat structs, with a one-to-one
3830 correspondence to the C<names> list.  If any name did not exist
3831 or could not be lstat'd, then the C<ino> field of that structure
3832 is set to C<-1>.
3833
3834 This call is intended for programs that want to efficiently
3835 list a directory contents without making many round-trips.
3836 See also C<guestfs_lxattrlist> for a similarly efficient call
3837 for getting extended attributes.  Very long directory listings
3838 might cause the protocol message size to be exceeded, causing
3839 this call to fail.  The caller must split up such requests
3840 into smaller groups of names.");
3841
3842   ("lxattrlist", (RStructList ("xattrs", "xattr"), [Pathname "path"; StringList "names"]), 205, [Optional "linuxxattrs"],
3843    [], (* XXX *)
3844    "lgetxattr on multiple files",
3845    "\
3846 This call allows you to get the extended attributes
3847 of multiple files, where all files are in the directory C<path>.
3848 C<names> is the list of files from this directory.
3849
3850 On return you get a flat list of xattr structs which must be
3851 interpreted sequentially.  The first xattr struct always has a zero-length
3852 C<attrname>.  C<attrval> in this struct is zero-length
3853 to indicate there was an error doing C<lgetxattr> for this
3854 file, I<or> is a C string which is a decimal number
3855 (the number of following attributes for this file, which could
3856 be C<\"0\">).  Then after the first xattr struct are the
3857 zero or more attributes for the first named file.
3858 This repeats for the second and subsequent files.
3859
3860 This call is intended for programs that want to efficiently
3861 list a directory contents without making many round-trips.
3862 See also C<guestfs_lstatlist> for a similarly efficient call
3863 for getting standard stats.  Very long directory listings
3864 might cause the protocol message size to be exceeded, causing
3865 this call to fail.  The caller must split up such requests
3866 into smaller groups of names.");
3867
3868   ("readlinklist", (RStringList "links", [Pathname "path"; StringList "names"]), 206, [],
3869    [], (* XXX *)
3870    "readlink on multiple files",
3871    "\
3872 This call allows you to do a C<readlink> operation
3873 on multiple files, where all files are in the directory C<path>.
3874 C<names> is the list of files from this directory.
3875
3876 On return you get a list of strings, with a one-to-one
3877 correspondence to the C<names> list.  Each string is the
3878 value of the symbol link.
3879
3880 If the C<readlink(2)> operation fails on any name, then
3881 the corresponding result string is the empty string C<\"\">.
3882 However the whole operation is completed even if there
3883 were C<readlink(2)> errors, and so you can call this
3884 function with names where you don't know if they are
3885 symbolic links already (albeit slightly less efficient).
3886
3887 This call is intended for programs that want to efficiently
3888 list a directory contents without making many round-trips.
3889 Very long directory listings might cause the protocol
3890 message size to be exceeded, causing
3891 this call to fail.  The caller must split up such requests
3892 into smaller groups of names.");
3893
3894   ("pread", (RBufferOut "content", [Pathname "path"; Int "count"; Int64 "offset"]), 207, [ProtocolLimitWarning],
3895    [InitISOFS, Always, TestOutputBuffer (
3896       [["pread"; "/known-4"; "1"; "3"]], "\n");
3897     InitISOFS, Always, TestOutputBuffer (
3898       [["pread"; "/empty"; "0"; "100"]], "")],
3899    "read part of a file",
3900    "\
3901 This command lets you read part of a file.  It reads C<count>
3902 bytes of the file, starting at C<offset>, from file C<path>.
3903
3904 This may read fewer bytes than requested.  For further details
3905 see the L<pread(2)> system call.");
3906
3907   ("part_init", (RErr, [Device "device"; String "parttype"]), 208, [],
3908    [InitEmpty, Always, TestRun (
3909       [["part_init"; "/dev/sda"; "gpt"]])],
3910    "create an empty partition table",
3911    "\
3912 This creates an empty partition table on C<device> of one of the
3913 partition types listed below.  Usually C<parttype> should be
3914 either C<msdos> or C<gpt> (for large disks).
3915
3916 Initially there are no partitions.  Following this, you should
3917 call C<guestfs_part_add> for each partition required.
3918
3919 Possible values for C<parttype> are:
3920
3921 =over 4
3922
3923 =item B<efi> | B<gpt>
3924
3925 Intel EFI / GPT partition table.
3926
3927 This is recommended for >= 2 TB partitions that will be accessed
3928 from Linux and Intel-based Mac OS X.  It also has limited backwards
3929 compatibility with the C<mbr> format.
3930
3931 =item B<mbr> | B<msdos>
3932
3933 The standard PC \"Master Boot Record\" (MBR) format used
3934 by MS-DOS and Windows.  This partition type will B<only> work
3935 for device sizes up to 2 TB.  For large disks we recommend
3936 using C<gpt>.
3937
3938 =back
3939
3940 Other partition table types that may work but are not
3941 supported include:
3942
3943 =over 4
3944
3945 =item B<aix>
3946
3947 AIX disk labels.
3948
3949 =item B<amiga> | B<rdb>
3950
3951 Amiga \"Rigid Disk Block\" format.
3952
3953 =item B<bsd>
3954
3955 BSD disk labels.
3956
3957 =item B<dasd>
3958
3959 DASD, used on IBM mainframes.
3960
3961 =item B<dvh>
3962
3963 MIPS/SGI volumes.
3964
3965 =item B<mac>
3966
3967 Old Mac partition format.  Modern Macs use C<gpt>.
3968
3969 =item B<pc98>
3970
3971 NEC PC-98 format, common in Japan apparently.
3972
3973 =item B<sun>
3974
3975 Sun disk labels.
3976
3977 =back");
3978
3979   ("part_add", (RErr, [Device "device"; String "prlogex"; Int64 "startsect"; Int64 "endsect"]), 209, [],
3980    [InitEmpty, Always, TestRun (
3981       [["part_init"; "/dev/sda"; "mbr"];
3982        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"]]);
3983     InitEmpty, Always, TestRun (
3984       [["part_init"; "/dev/sda"; "gpt"];
3985        ["part_add"; "/dev/sda"; "primary"; "34"; "127"];
3986        ["part_add"; "/dev/sda"; "primary"; "128"; "-34"]]);
3987     InitEmpty, Always, TestRun (
3988       [["part_init"; "/dev/sda"; "mbr"];
3989        ["part_add"; "/dev/sda"; "primary"; "32"; "127"];
3990        ["part_add"; "/dev/sda"; "primary"; "128"; "255"];
3991        ["part_add"; "/dev/sda"; "primary"; "256"; "511"];
3992        ["part_add"; "/dev/sda"; "primary"; "512"; "-1"]])],
3993    "add a partition to the device",
3994    "\
3995 This command adds a partition to C<device>.  If there is no partition
3996 table on the device, call C<guestfs_part_init> first.
3997
3998 The C<prlogex> parameter is the type of partition.  Normally you
3999 should pass C<p> or C<primary> here, but MBR partition tables also
4000 support C<l> (or C<logical>) and C<e> (or C<extended>) partition
4001 types.
4002
4003 C<startsect> and C<endsect> are the start and end of the partition
4004 in I<sectors>.  C<endsect> may be negative, which means it counts
4005 backwards from the end of the disk (C<-1> is the last sector).
4006
4007 Creating a partition which covers the whole disk is not so easy.
4008 Use C<guestfs_part_disk> to do that.");
4009
4010   ("part_disk", (RErr, [Device "device"; String "parttype"]), 210, [DangerWillRobinson],
4011    [InitEmpty, Always, TestRun (
4012       [["part_disk"; "/dev/sda"; "mbr"]]);
4013     InitEmpty, Always, TestRun (
4014       [["part_disk"; "/dev/sda"; "gpt"]])],
4015    "partition whole disk with a single primary partition",
4016    "\
4017 This command is simply a combination of C<guestfs_part_init>
4018 followed by C<guestfs_part_add> to create a single primary partition
4019 covering the whole disk.
4020
4021 C<parttype> is the partition table type, usually C<mbr> or C<gpt>,
4022 but other possible values are described in C<guestfs_part_init>.");
4023
4024   ("part_set_bootable", (RErr, [Device "device"; Int "partnum"; Bool "bootable"]), 211, [],
4025    [InitEmpty, Always, TestRun (
4026       [["part_disk"; "/dev/sda"; "mbr"];
4027        ["part_set_bootable"; "/dev/sda"; "1"; "true"]])],
4028    "make a partition bootable",
4029    "\
4030 This sets the bootable flag on partition numbered C<partnum> on
4031 device C<device>.  Note that partitions are numbered from 1.
4032
4033 The bootable flag is used by some PC BIOSes to determine which
4034 partition to boot from.  It is by no means universally recognized,
4035 and in any case if your operating system installed a boot
4036 sector on the device itself, then that takes precedence.");
4037
4038   ("part_set_name", (RErr, [Device "device"; Int "partnum"; String "name"]), 212, [],
4039    [InitEmpty, Always, TestRun (
4040       [["part_disk"; "/dev/sda"; "gpt"];
4041        ["part_set_name"; "/dev/sda"; "1"; "thepartname"]])],
4042    "set partition name",
4043    "\
4044 This sets the partition name on partition numbered C<partnum> on
4045 device C<device>.  Note that partitions are numbered from 1.
4046
4047 The partition name can only be set on certain types of partition
4048 table.  This works on C<gpt> but not on C<mbr> partitions.");
4049
4050   ("part_list", (RStructList ("partitions", "partition"), [Device "device"]), 213, [],
4051    [], (* XXX Add a regression test for this. *)
4052    "list partitions on a device",
4053    "\
4054 This command parses the partition table on C<device> and
4055 returns the list of partitions found.
4056
4057 The fields in the returned structure are:
4058
4059 =over 4
4060
4061 =item B<part_num>
4062
4063 Partition number, counting from 1.
4064
4065 =item B<part_start>
4066
4067 Start of the partition I<in bytes>.  To get sectors you have to
4068 divide by the device's sector size, see C<guestfs_blockdev_getss>.
4069
4070 =item B<part_end>
4071
4072 End of the partition in bytes.
4073
4074 =item B<part_size>
4075
4076 Size of the partition in bytes.
4077
4078 =back");
4079
4080   ("part_get_parttype", (RString "parttype", [Device "device"]), 214, [],
4081    [InitEmpty, Always, TestOutput (
4082       [["part_disk"; "/dev/sda"; "gpt"];
4083        ["part_get_parttype"; "/dev/sda"]], "gpt")],
4084    "get the partition table type",
4085    "\
4086 This command examines the partition table on C<device> and
4087 returns the partition table type (format) being used.
4088
4089 Common return values include: C<msdos> (a DOS/Windows style MBR
4090 partition table), C<gpt> (a GPT/EFI-style partition table).  Other
4091 values are possible, although unusual.  See C<guestfs_part_init>
4092 for a full list.");
4093
4094   ("fill", (RErr, [Int "c"; Int "len"; Pathname "path"]), 215, [],
4095    [InitBasicFS, Always, TestOutputBuffer (
4096       [["fill"; "0x63"; "10"; "/test"];
4097        ["read_file"; "/test"]], "cccccccccc")],
4098    "fill a file with octets",
4099    "\
4100 This command creates a new file called C<path>.  The initial
4101 content of the file is C<len> octets of C<c>, where C<c>
4102 must be a number in the range C<[0..255]>.
4103
4104 To fill a file with zero bytes (sparsely), it is
4105 much more efficient to use C<guestfs_truncate_size>.");
4106
4107   ("available", (RErr, [StringList "groups"]), 216, [],
4108    [],
4109    "test availability of some parts of the API",
4110    "\
4111 This command is used to check the availability of some
4112 groups of libguestfs functions which not all builds of
4113 libguestfs will be able to provide.
4114
4115 The precise libguestfs function groups that may be checked by this
4116 command are listed in L<guestfs(3)/AVAILABILITY>.
4117
4118 The argument C<groups> is a list of API group names, eg:
4119 C<[\"inotify\", \"augeas\"]> would check for the availability of
4120 the C<guestfs_inotify_*> functions and C<guestfs_aug_*>
4121 (partition editing) functions.
4122
4123 The command returns no error if I<all> requested groups are available.
4124
4125 It returns an error if one or more of the requested
4126 groups is unavailable.
4127
4128 If an unknown group name is included in the
4129 list of C<groups> then an error is always returned.
4130
4131 I<Notes:>
4132
4133 =over 4
4134
4135 =item *
4136
4137 You must call C<guestfs_launch> before calling this function.
4138 The reason is because we don't know what function groups are
4139 supported by the appliance/daemon until it is running and can
4140 be queried.
4141
4142 =item *
4143
4144 If a group of functions is available, this does not necessarily
4145 mean that they will work.  You still have to check for errors
4146 when calling individual API functions even if they are
4147 available.
4148
4149 =item *
4150
4151 It is usually the job of distro packagers to build
4152 complete functionality into the libguestfs appliance.
4153 Upstream libguestfs, if built from source with all
4154 requirements satisfied, will support everything.
4155
4156 =item *
4157
4158 This call was added in version C<1.0.80>.  In previous
4159 versions of libguestfs all you could do would be to speculatively
4160 execute a command to find out if the daemon implemented it.
4161 See also C<guestfs_version>.
4162
4163 =back");
4164
4165 ]
4166
4167 let all_functions = non_daemon_functions @ daemon_functions
4168
4169 (* In some places we want the functions to be displayed sorted
4170  * alphabetically, so this is useful:
4171  *)
4172 let all_functions_sorted =
4173   List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
4174                compare n1 n2) all_functions
4175
4176 (* Field types for structures. *)
4177 type field =
4178   | FChar                       (* C 'char' (really, a 7 bit byte). *)
4179   | FString                     (* nul-terminated ASCII string, NOT NULL. *)
4180   | FBuffer                     (* opaque buffer of bytes, (char *, int) pair *)
4181   | FUInt32
4182   | FInt32
4183   | FUInt64
4184   | FInt64
4185   | FBytes                      (* Any int measure that counts bytes. *)
4186   | FUUID                       (* 32 bytes long, NOT nul-terminated. *)
4187   | FOptPercent                 (* [0..100], or -1 meaning "not present". *)
4188
4189 (* Because we generate extra parsing code for LVM command line tools,
4190  * we have to pull out the LVM columns separately here.
4191  *)
4192 let lvm_pv_cols = [
4193   "pv_name", FString;
4194   "pv_uuid", FUUID;
4195   "pv_fmt", FString;
4196   "pv_size", FBytes;
4197   "dev_size", FBytes;
4198   "pv_free", FBytes;
4199   "pv_used", FBytes;
4200   "pv_attr", FString (* XXX *);
4201   "pv_pe_count", FInt64;
4202   "pv_pe_alloc_count", FInt64;
4203   "pv_tags", FString;
4204   "pe_start", FBytes;
4205   "pv_mda_count", FInt64;
4206   "pv_mda_free", FBytes;
4207   (* Not in Fedora 10:
4208      "pv_mda_size", FBytes;
4209   *)
4210 ]
4211 let lvm_vg_cols = [
4212   "vg_name", FString;
4213   "vg_uuid", FUUID;
4214   "vg_fmt", FString;
4215   "vg_attr", FString (* XXX *);
4216   "vg_size", FBytes;
4217   "vg_free", FBytes;
4218   "vg_sysid", FString;
4219   "vg_extent_size", FBytes;
4220   "vg_extent_count", FInt64;
4221   "vg_free_count", FInt64;
4222   "max_lv", FInt64;
4223   "max_pv", FInt64;
4224   "pv_count", FInt64;
4225   "lv_count", FInt64;
4226   "snap_count", FInt64;
4227   "vg_seqno", FInt64;
4228   "vg_tags", FString;
4229   "vg_mda_count", FInt64;
4230   "vg_mda_free", FBytes;
4231   (* Not in Fedora 10:
4232      "vg_mda_size", FBytes;
4233   *)
4234 ]
4235 let lvm_lv_cols = [
4236   "lv_name", FString;
4237   "lv_uuid", FUUID;
4238   "lv_attr", FString (* XXX *);
4239   "lv_major", FInt64;
4240   "lv_minor", FInt64;
4241   "lv_kernel_major", FInt64;
4242   "lv_kernel_minor", FInt64;
4243   "lv_size", FBytes;
4244   "seg_count", FInt64;
4245   "origin", FString;
4246   "snap_percent", FOptPercent;
4247   "copy_percent", FOptPercent;
4248   "move_pv", FString;
4249   "lv_tags", FString;
4250   "mirror_log", FString;
4251   "modules", FString;
4252 ]
4253
4254 (* Names and fields in all structures (in RStruct and RStructList)
4255  * that we support.
4256  *)
4257 let structs = [
4258   (* The old RIntBool return type, only ever used for aug_defnode.  Do
4259    * not use this struct in any new code.
4260    *)
4261   "int_bool", [
4262     "i", FInt32;                (* for historical compatibility *)
4263     "b", FInt32;                (* for historical compatibility *)
4264   ];
4265
4266   (* LVM PVs, VGs, LVs. *)
4267   "lvm_pv", lvm_pv_cols;
4268   "lvm_vg", lvm_vg_cols;
4269   "lvm_lv", lvm_lv_cols;
4270
4271   (* Column names and types from stat structures.
4272    * NB. Can't use things like 'st_atime' because glibc header files
4273    * define some of these as macros.  Ugh.
4274    *)
4275   "stat", [
4276     "dev", FInt64;
4277     "ino", FInt64;
4278     "mode", FInt64;
4279     "nlink", FInt64;
4280     "uid", FInt64;
4281     "gid", FInt64;
4282     "rdev", FInt64;
4283     "size", FInt64;
4284     "blksize", FInt64;
4285     "blocks", FInt64;
4286     "atime", FInt64;
4287     "mtime", FInt64;
4288     "ctime", FInt64;
4289   ];
4290   "statvfs", [
4291     "bsize", FInt64;
4292     "frsize", FInt64;
4293     "blocks", FInt64;
4294     "bfree", FInt64;
4295     "bavail", FInt64;
4296     "files", FInt64;
4297     "ffree", FInt64;
4298     "favail", FInt64;
4299     "fsid", FInt64;
4300     "flag", FInt64;
4301     "namemax", FInt64;
4302   ];
4303
4304   (* Column names in dirent structure. *)
4305   "dirent", [
4306     "ino", FInt64;
4307     (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
4308     "ftyp", FChar;
4309     "name", FString;
4310   ];
4311
4312   (* Version numbers. *)
4313   "version", [
4314     "major", FInt64;
4315     "minor", FInt64;
4316     "release", FInt64;
4317     "extra", FString;
4318   ];
4319
4320   (* Extended attribute. *)
4321   "xattr", [
4322     "attrname", FString;
4323     "attrval", FBuffer;
4324   ];
4325
4326   (* Inotify events. *)
4327   "inotify_event", [
4328     "in_wd", FInt64;
4329     "in_mask", FUInt32;
4330     "in_cookie", FUInt32;
4331     "in_name", FString;
4332   ];
4333
4334   (* Partition table entry. *)
4335   "partition", [
4336     "part_num", FInt32;
4337     "part_start", FBytes;
4338     "part_end", FBytes;
4339     "part_size", FBytes;
4340   ];
4341 ] (* end of structs *)
4342
4343 (* Ugh, Java has to be different ..
4344  * These names are also used by the Haskell bindings.
4345  *)
4346 let java_structs = [
4347   "int_bool", "IntBool";
4348   "lvm_pv", "PV";
4349   "lvm_vg", "VG";
4350   "lvm_lv", "LV";
4351   "stat", "Stat";
4352   "statvfs", "StatVFS";
4353   "dirent", "Dirent";
4354   "version", "Version";
4355   "xattr", "XAttr";
4356   "inotify_event", "INotifyEvent";
4357   "partition", "Partition";
4358 ]
4359
4360 (* What structs are actually returned. *)
4361 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
4362
4363 (* Returns a list of RStruct/RStructList structs that are returned
4364  * by any function.  Each element of returned list is a pair:
4365  *
4366  * (structname, RStructOnly)
4367  *    == there exists function which returns RStruct (_, structname)
4368  * (structname, RStructListOnly)
4369  *    == there exists function which returns RStructList (_, structname)
4370  * (structname, RStructAndList)
4371  *    == there are functions returning both RStruct (_, structname)
4372  *                                      and RStructList (_, structname)
4373  *)
4374 let rstructs_used_by functions =
4375   (* ||| is a "logical OR" for rstructs_used_t *)
4376   let (|||) a b =
4377     match a, b with
4378     | RStructAndList, _
4379     | _, RStructAndList -> RStructAndList
4380     | RStructOnly, RStructListOnly
4381     | RStructListOnly, RStructOnly -> RStructAndList
4382     | RStructOnly, RStructOnly -> RStructOnly
4383     | RStructListOnly, RStructListOnly -> RStructListOnly
4384   in
4385
4386   let h = Hashtbl.create 13 in
4387
4388   (* if elem->oldv exists, update entry using ||| operator,
4389    * else just add elem->newv to the hash
4390    *)
4391   let update elem newv =
4392     try  let oldv = Hashtbl.find h elem in
4393          Hashtbl.replace h elem (newv ||| oldv)
4394     with Not_found -> Hashtbl.add h elem newv
4395   in
4396
4397   List.iter (
4398     fun (_, style, _, _, _, _, _) ->
4399       match fst style with
4400       | RStruct (_, structname) -> update structname RStructOnly
4401       | RStructList (_, structname) -> update structname RStructListOnly
4402       | _ -> ()
4403   ) functions;
4404
4405   (* return key->values as a list of (key,value) *)
4406   Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
4407
4408 (* Used for testing language bindings. *)
4409 type callt =
4410   | CallString of string
4411   | CallOptString of string option
4412   | CallStringList of string list
4413   | CallInt of int
4414   | CallInt64 of int64
4415   | CallBool of bool
4416
4417 (* Used to memoize the result of pod2text. *)
4418 let pod2text_memo_filename = "src/.pod2text.data"
4419 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
4420   try
4421     let chan = open_in pod2text_memo_filename in
4422     let v = input_value chan in
4423     close_in chan;
4424     v
4425   with
4426     _ -> Hashtbl.create 13
4427 let pod2text_memo_updated () =
4428   let chan = open_out pod2text_memo_filename in
4429   output_value chan pod2text_memo;
4430   close_out chan
4431
4432 (* Useful functions.
4433  * Note we don't want to use any external OCaml libraries which
4434  * makes this a bit harder than it should be.
4435  *)
4436 let failwithf fs = ksprintf failwith fs
4437
4438 let replace_char s c1 c2 =
4439   let s2 = String.copy s in
4440   let r = ref false in
4441   for i = 0 to String.length s2 - 1 do
4442     if String.unsafe_get s2 i = c1 then (
4443       String.unsafe_set s2 i c2;
4444       r := true
4445     )
4446   done;
4447   if not !r then s else s2
4448
4449 let isspace c =
4450   c = ' '
4451   (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
4452
4453 let triml ?(test = isspace) str =
4454   let i = ref 0 in
4455   let n = ref (String.length str) in
4456   while !n > 0 && test str.[!i]; do
4457     decr n;
4458     incr i
4459   done;
4460   if !i = 0 then str
4461   else String.sub str !i !n
4462
4463 let trimr ?(test = isspace) str =
4464   let n = ref (String.length str) in
4465   while !n > 0 && test str.[!n-1]; do
4466     decr n
4467   done;
4468   if !n = String.length str then str
4469   else String.sub str 0 !n
4470
4471 let trim ?(test = isspace) str =
4472   trimr ~test (triml ~test str)
4473
4474 let rec find s sub =
4475   let len = String.length s in
4476   let sublen = String.length sub in
4477   let rec loop i =
4478     if i <= len-sublen then (
4479       let rec loop2 j =
4480         if j < sublen then (
4481           if s.[i+j] = sub.[j] then loop2 (j+1)
4482           else -1
4483         ) else
4484           i (* found *)
4485       in
4486       let r = loop2 0 in
4487       if r = -1 then loop (i+1) else r
4488     ) else
4489       -1 (* not found *)
4490   in
4491   loop 0
4492
4493 let rec replace_str s s1 s2 =
4494   let len = String.length s in
4495   let sublen = String.length s1 in
4496   let i = find s s1 in
4497   if i = -1 then s
4498   else (
4499     let s' = String.sub s 0 i in
4500     let s'' = String.sub s (i+sublen) (len-i-sublen) in
4501     s' ^ s2 ^ replace_str s'' s1 s2
4502   )
4503
4504 let rec string_split sep str =
4505   let len = String.length str in
4506   let seplen = String.length sep in
4507   let i = find str sep in
4508   if i = -1 then [str]
4509   else (
4510     let s' = String.sub str 0 i in
4511     let s'' = String.sub str (i+seplen) (len-i-seplen) in
4512     s' :: string_split sep s''
4513   )
4514
4515 let files_equal n1 n2 =
4516   let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
4517   match Sys.command cmd with
4518   | 0 -> true
4519   | 1 -> false
4520   | i -> failwithf "%s: failed with error code %d" cmd i
4521
4522 let rec filter_map f = function
4523   | [] -> []
4524   | x :: xs ->
4525       match f x with
4526       | Some y -> y :: filter_map f xs
4527       | None -> filter_map f xs
4528
4529 let rec find_map f = function
4530   | [] -> raise Not_found
4531   | x :: xs ->
4532       match f x with
4533       | Some y -> y
4534       | None -> find_map f xs
4535
4536 let iteri f xs =
4537   let rec loop i = function
4538     | [] -> ()
4539     | x :: xs -> f i x; loop (i+1) xs
4540   in
4541   loop 0 xs
4542
4543 let mapi f xs =
4544   let rec loop i = function
4545     | [] -> []
4546     | x :: xs -> let r = f i x in r :: loop (i+1) xs
4547   in
4548   loop 0 xs
4549
4550 let name_of_argt = function
4551   | Pathname n | Device n | Dev_or_Path n | String n | OptString n
4552   | StringList n | DeviceList n | Bool n | Int n | Int64 n
4553   | FileIn n | FileOut n -> n
4554
4555 let java_name_of_struct typ =
4556   try List.assoc typ java_structs
4557   with Not_found ->
4558     failwithf
4559       "java_name_of_struct: no java_structs entry corresponding to %s" typ
4560
4561 let cols_of_struct typ =
4562   try List.assoc typ structs
4563   with Not_found ->
4564     failwithf "cols_of_struct: unknown struct %s" typ
4565
4566 let seq_of_test = function
4567   | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
4568   | TestOutputListOfDevices (s, _)
4569   | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
4570   | TestOutputTrue s | TestOutputFalse s
4571   | TestOutputLength (s, _) | TestOutputBuffer (s, _)
4572   | TestOutputStruct (s, _)
4573   | TestLastFail s -> s
4574
4575 (* Handling for function flags. *)
4576 let protocol_limit_warning =
4577   "Because of the message protocol, there is a transfer limit
4578 of somewhere between 2MB and 4MB.  To transfer large files you should use
4579 FTP."
4580
4581 let danger_will_robinson =
4582   "B<This command is dangerous.  Without careful use you
4583 can easily destroy all your data>."
4584
4585 let deprecation_notice flags =
4586   try
4587     let alt =
4588       find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
4589     let txt =
4590       sprintf "This function is deprecated.
4591 In new code, use the C<%s> call instead.
4592
4593 Deprecated functions will not be removed from the API, but the
4594 fact that they are deprecated indicates that there are problems
4595 with correct use of these functions." alt in
4596     Some txt
4597   with
4598     Not_found -> None
4599
4600 (* Create list of optional groups. *)
4601 let optgroups =
4602   let h = Hashtbl.create 13 in
4603   List.iter (
4604     fun (name, _, _, flags, _, _, _) ->
4605       List.iter (
4606         function
4607         | Optional group ->
4608             let names = try Hashtbl.find h group with Not_found -> [] in
4609             Hashtbl.replace h group (name :: names)
4610         | _ -> ()
4611       ) flags
4612   ) daemon_functions;
4613   let groups = Hashtbl.fold (fun k _ ks -> k :: ks) h [] in
4614   let groups =
4615     List.map (
4616       fun group -> group, List.sort compare (Hashtbl.find h group)
4617     ) groups in
4618   List.sort (fun x y -> compare (fst x) (fst y)) groups
4619
4620 (* Check function names etc. for consistency. *)
4621 let check_functions () =
4622   let contains_uppercase str =
4623     let len = String.length str in
4624     let rec loop i =
4625       if i >= len then false
4626       else (
4627         let c = str.[i] in
4628         if c >= 'A' && c <= 'Z' then true
4629         else loop (i+1)
4630       )
4631     in
4632     loop 0
4633   in
4634
4635   (* Check function names. *)
4636   List.iter (
4637     fun (name, _, _, _, _, _, _) ->
4638       if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
4639         failwithf "function name %s does not need 'guestfs' prefix" name;
4640       if name = "" then
4641         failwithf "function name is empty";
4642       if name.[0] < 'a' || name.[0] > 'z' then
4643         failwithf "function name %s must start with lowercase a-z" name;
4644       if String.contains name '-' then
4645         failwithf "function name %s should not contain '-', use '_' instead."
4646           name
4647   ) all_functions;
4648
4649   (* Check function parameter/return names. *)
4650   List.iter (
4651     fun (name, style, _, _, _, _, _) ->
4652       let check_arg_ret_name n =
4653         if contains_uppercase n then
4654           failwithf "%s param/ret %s should not contain uppercase chars"
4655             name n;
4656         if String.contains n '-' || String.contains n '_' then
4657           failwithf "%s param/ret %s should not contain '-' or '_'"
4658             name n;
4659         if n = "value" then
4660           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;
4661         if n = "int" || n = "char" || n = "short" || n = "long" then
4662           failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
4663         if n = "i" || n = "n" then
4664           failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
4665         if n = "argv" || n = "args" then
4666           failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
4667
4668         (* List Haskell, OCaml and C keywords here.
4669          * http://www.haskell.org/haskellwiki/Keywords
4670          * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
4671          * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
4672          * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
4673          *   |perl -pe 's/(.+)/"$1";/'|fmt -70
4674          * Omitting _-containing words, since they're handled above.
4675          * Omitting the OCaml reserved word, "val", is ok,
4676          * and saves us from renaming several parameters.
4677          *)
4678         let reserved = [
4679           "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
4680           "char"; "class"; "const"; "constraint"; "continue"; "data";
4681           "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
4682           "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
4683           "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
4684           "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
4685           "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
4686           "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
4687           "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
4688           "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
4689           "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
4690           "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
4691           "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
4692           "volatile"; "when"; "where"; "while";
4693           ] in
4694         if List.mem n reserved then
4695           failwithf "%s has param/ret using reserved word %s" name n;
4696       in
4697
4698       (match fst style with
4699        | RErr -> ()
4700        | RInt n | RInt64 n | RBool n
4701        | RConstString n | RConstOptString n | RString n
4702        | RStringList n | RStruct (n, _) | RStructList (n, _)
4703        | RHashtable n | RBufferOut n ->
4704            check_arg_ret_name n
4705       );
4706       List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
4707   ) all_functions;
4708
4709   (* Check short descriptions. *)
4710   List.iter (
4711     fun (name, _, _, _, _, shortdesc, _) ->
4712       if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
4713         failwithf "short description of %s should begin with lowercase." name;
4714       let c = shortdesc.[String.length shortdesc-1] in
4715       if c = '\n' || c = '.' then
4716         failwithf "short description of %s should not end with . or \\n." name
4717   ) all_functions;
4718
4719   (* Check long dscriptions. *)
4720   List.iter (
4721     fun (name, _, _, _, _, _, longdesc) ->
4722       if longdesc.[String.length longdesc-1] = '\n' then
4723         failwithf "long description of %s should not end with \\n." name
4724   ) all_functions;
4725
4726   (* Check proc_nrs. *)
4727   List.iter (
4728     fun (name, _, proc_nr, _, _, _, _) ->
4729       if proc_nr <= 0 then
4730         failwithf "daemon function %s should have proc_nr > 0" name
4731   ) daemon_functions;
4732
4733   List.iter (
4734     fun (name, _, proc_nr, _, _, _, _) ->
4735       if proc_nr <> -1 then
4736         failwithf "non-daemon function %s should have proc_nr -1" name
4737   ) non_daemon_functions;
4738
4739   let proc_nrs =
4740     List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
4741       daemon_functions in
4742   let proc_nrs =
4743     List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
4744   let rec loop = function
4745     | [] -> ()
4746     | [_] -> ()
4747     | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
4748         loop rest
4749     | (name1,nr1) :: (name2,nr2) :: _ ->
4750         failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
4751           name1 name2 nr1 nr2
4752   in
4753   loop proc_nrs;
4754
4755   (* Check tests. *)
4756   List.iter (
4757     function
4758       (* Ignore functions that have no tests.  We generate a
4759        * warning when the user does 'make check' instead.
4760        *)
4761     | name, _, _, _, [], _, _ -> ()
4762     | name, _, _, _, tests, _, _ ->
4763         let funcs =
4764           List.map (
4765             fun (_, _, test) ->
4766               match seq_of_test test with
4767               | [] ->
4768                   failwithf "%s has a test containing an empty sequence" name
4769               | cmds -> List.map List.hd cmds
4770           ) tests in
4771         let funcs = List.flatten funcs in
4772
4773         let tested = List.mem name funcs in
4774
4775         if not tested then
4776           failwithf "function %s has tests but does not test itself" name
4777   ) all_functions
4778
4779 (* 'pr' prints to the current output file. *)
4780 let chan = ref Pervasives.stdout
4781 let pr fs = ksprintf (output_string !chan) fs
4782
4783 (* Generate a header block in a number of standard styles. *)
4784 type comment_style = CStyle | HashStyle | OCamlStyle | HaskellStyle
4785 type license = GPLv2 | LGPLv2
4786
4787 let generate_header comment license =
4788   let c = match comment with
4789     | CStyle ->     pr "/* "; " *"
4790     | HashStyle ->  pr "# ";  "#"
4791     | OCamlStyle -> pr "(* "; " *"
4792     | HaskellStyle -> pr "{- "; "  " in
4793   pr "libguestfs generated file\n";
4794   pr "%s WARNING: THIS FILE IS GENERATED BY 'src/generator.ml'.\n" c;
4795   pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
4796   pr "%s\n" c;
4797   pr "%s Copyright (C) 2009 Red Hat Inc.\n" c;
4798   pr "%s\n" c;
4799   (match license with
4800    | GPLv2 ->
4801        pr "%s This program is free software; you can redistribute it and/or modify\n" c;
4802        pr "%s it under the terms of the GNU General Public License as published by\n" c;
4803        pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
4804        pr "%s (at your option) any later version.\n" c;
4805        pr "%s\n" c;
4806        pr "%s This program is distributed in the hope that it will be useful,\n" c;
4807        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
4808        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n" c;
4809        pr "%s GNU General Public License for more details.\n" c;
4810        pr "%s\n" c;
4811        pr "%s You should have received a copy of the GNU General Public License along\n" c;
4812        pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
4813        pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
4814
4815    | LGPLv2 ->
4816        pr "%s This library is free software; you can redistribute it and/or\n" c;
4817        pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
4818        pr "%s License as published by the Free Software Foundation; either\n" c;
4819        pr "%s version 2 of the License, or (at your option) any later version.\n" c;
4820        pr "%s\n" c;
4821        pr "%s This library is distributed in the hope that it will be useful,\n" c;
4822        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
4823        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n" c;
4824        pr "%s Lesser General Public License for more details.\n" c;
4825        pr "%s\n" c;
4826        pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
4827        pr "%s License along with this library; if not, write to the Free Software\n" c;
4828        pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
4829   );
4830   (match comment with
4831    | CStyle -> pr " */\n"
4832    | HashStyle -> ()
4833    | OCamlStyle -> pr " *)\n"
4834    | HaskellStyle -> pr "-}\n"
4835   );
4836   pr "\n"
4837
4838 (* Start of main code generation functions below this line. *)
4839
4840 (* Generate the pod documentation for the C API. *)
4841 let rec generate_actions_pod () =
4842   List.iter (
4843     fun (shortname, style, _, flags, _, _, longdesc) ->
4844       if not (List.mem NotInDocs flags) then (
4845         let name = "guestfs_" ^ shortname in
4846         pr "=head2 %s\n\n" name;
4847         pr " ";
4848         generate_prototype ~extern:false ~handle:"handle" name style;
4849         pr "\n\n";
4850         pr "%s\n\n" longdesc;
4851         (match fst style with
4852          | RErr ->
4853              pr "This function returns 0 on success or -1 on error.\n\n"
4854          | RInt _ ->
4855              pr "On error this function returns -1.\n\n"
4856          | RInt64 _ ->
4857              pr "On error this function returns -1.\n\n"
4858          | RBool _ ->
4859              pr "This function returns a C truth value on success or -1 on error.\n\n"
4860          | RConstString _ ->
4861              pr "This function returns a string, or NULL on error.
4862 The string is owned by the guest handle and must I<not> be freed.\n\n"
4863          | RConstOptString _ ->
4864              pr "This function returns a string which may be NULL.
4865 There is way to return an error from this function.
4866 The string is owned by the guest handle and must I<not> be freed.\n\n"
4867          | RString _ ->
4868              pr "This function returns a string, or NULL on error.
4869 I<The caller must free the returned string after use>.\n\n"
4870          | RStringList _ ->
4871              pr "This function returns a NULL-terminated array of strings
4872 (like L<environ(3)>), or NULL if there was an error.
4873 I<The caller must free the strings and the array after use>.\n\n"
4874          | RStruct (_, typ) ->
4875              pr "This function returns a C<struct guestfs_%s *>,
4876 or NULL if there was an error.
4877 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
4878          | RStructList (_, typ) ->
4879              pr "This function returns a C<struct guestfs_%s_list *>
4880 (see E<lt>guestfs-structs.hE<gt>),
4881 or NULL if there was an error.
4882 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
4883          | RHashtable _ ->
4884              pr "This function returns a NULL-terminated array of
4885 strings, or NULL if there was an error.
4886 The array of strings will always have length C<2n+1>, where
4887 C<n> keys and values alternate, followed by the trailing NULL entry.
4888 I<The caller must free the strings and the array after use>.\n\n"
4889          | RBufferOut _ ->
4890              pr "This function returns a buffer, or NULL on error.
4891 The size of the returned buffer is written to C<*size_r>.
4892 I<The caller must free the returned buffer after use>.\n\n"
4893         );
4894         if List.mem ProtocolLimitWarning flags then
4895           pr "%s\n\n" protocol_limit_warning;
4896         if List.mem DangerWillRobinson flags then
4897           pr "%s\n\n" danger_will_robinson;
4898         match deprecation_notice flags with
4899         | None -> ()
4900         | Some txt -> pr "%s\n\n" txt
4901       )
4902   ) all_functions_sorted
4903
4904 and generate_structs_pod () =
4905   (* Structs documentation. *)
4906   List.iter (
4907     fun (typ, cols) ->
4908       pr "=head2 guestfs_%s\n" typ;
4909       pr "\n";
4910       pr " struct guestfs_%s {\n" typ;
4911       List.iter (
4912         function
4913         | name, FChar -> pr "   char %s;\n" name
4914         | name, FUInt32 -> pr "   uint32_t %s;\n" name
4915         | name, FInt32 -> pr "   int32_t %s;\n" name
4916         | name, (FUInt64|FBytes) -> pr "   uint64_t %s;\n" name
4917         | name, FInt64 -> pr "   int64_t %s;\n" name
4918         | name, FString -> pr "   char *%s;\n" name
4919         | name, FBuffer ->
4920             pr "   /* The next two fields describe a byte array. */\n";
4921             pr "   uint32_t %s_len;\n" name;
4922             pr "   char *%s;\n" name
4923         | name, FUUID ->
4924             pr "   /* The next field is NOT nul-terminated, be careful when printing it: */\n";
4925             pr "   char %s[32];\n" name
4926         | name, FOptPercent ->
4927             pr "   /* The next field is [0..100] or -1 meaning 'not present': */\n";
4928             pr "   float %s;\n" name
4929       ) cols;
4930       pr " };\n";
4931       pr " \n";
4932       pr " struct guestfs_%s_list {\n" typ;
4933       pr "   uint32_t len; /* Number of elements in list. */\n";
4934       pr "   struct guestfs_%s *val; /* Elements. */\n" typ;
4935       pr " };\n";
4936       pr " \n";
4937       pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
4938       pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
4939         typ typ;
4940       pr "\n"
4941   ) structs
4942
4943 and generate_availability_pod () =
4944   (* Availability documentation. *)
4945   pr "=over 4\n";
4946   pr "\n";
4947   List.iter (
4948     fun (group, functions) ->
4949       pr "=item B<%s>\n" group;
4950       pr "\n";
4951       pr "The following functions:\n";
4952       List.iter (pr "L</guestfs_%s>\n") functions;
4953       pr "\n"
4954   ) optgroups;
4955   pr "=back\n";
4956   pr "\n"
4957
4958 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
4959  * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
4960  *
4961  * We have to use an underscore instead of a dash because otherwise
4962  * rpcgen generates incorrect code.
4963  *
4964  * This header is NOT exported to clients, but see also generate_structs_h.
4965  *)
4966 and generate_xdr () =
4967   generate_header CStyle LGPLv2;
4968
4969   (* This has to be defined to get around a limitation in Sun's rpcgen. *)
4970   pr "typedef string str<>;\n";
4971   pr "\n";
4972
4973   (* Internal structures. *)
4974   List.iter (
4975     function
4976     | typ, cols ->
4977         pr "struct guestfs_int_%s {\n" typ;
4978         List.iter (function
4979                    | name, FChar -> pr "  char %s;\n" name
4980                    | name, FString -> pr "  string %s<>;\n" name
4981                    | name, FBuffer -> pr "  opaque %s<>;\n" name
4982                    | name, FUUID -> pr "  opaque %s[32];\n" name
4983                    | name, (FInt32|FUInt32) -> pr "  int %s;\n" name
4984                    | name, (FInt64|FUInt64|FBytes) -> pr "  hyper %s;\n" name
4985                    | name, FOptPercent -> pr "  float %s;\n" name
4986                   ) cols;
4987         pr "};\n";
4988         pr "\n";
4989         pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
4990         pr "\n";
4991   ) structs;
4992
4993   List.iter (
4994     fun (shortname, style, _, _, _, _, _) ->
4995       let name = "guestfs_" ^ shortname in
4996
4997       (match snd style with
4998        | [] -> ()
4999        | args ->
5000            pr "struct %s_args {\n" name;
5001            List.iter (
5002              function
5003              | Pathname n | Device n | Dev_or_Path n | String n ->
5004                  pr "  string %s<>;\n" n
5005              | OptString n -> pr "  str *%s;\n" n
5006              | StringList n | DeviceList n -> pr "  str %s<>;\n" n
5007              | Bool n -> pr "  bool %s;\n" n
5008              | Int n -> pr "  int %s;\n" n
5009              | Int64 n -> pr "  hyper %s;\n" n
5010              | FileIn _ | FileOut _ -> ()
5011            ) args;
5012            pr "};\n\n"
5013       );
5014       (match fst style with
5015        | RErr -> ()
5016        | RInt n ->
5017            pr "struct %s_ret {\n" name;
5018            pr "  int %s;\n" n;
5019            pr "};\n\n"
5020        | RInt64 n ->
5021            pr "struct %s_ret {\n" name;
5022            pr "  hyper %s;\n" n;
5023            pr "};\n\n"
5024        | RBool n ->
5025            pr "struct %s_ret {\n" name;
5026            pr "  bool %s;\n" n;
5027            pr "};\n\n"
5028        | RConstString _ | RConstOptString _ ->
5029            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5030        | RString n ->
5031            pr "struct %s_ret {\n" name;
5032            pr "  string %s<>;\n" n;
5033            pr "};\n\n"
5034        | RStringList n ->
5035            pr "struct %s_ret {\n" name;
5036            pr "  str %s<>;\n" n;
5037            pr "};\n\n"
5038        | RStruct (n, typ) ->
5039            pr "struct %s_ret {\n" name;
5040            pr "  guestfs_int_%s %s;\n" typ n;
5041            pr "};\n\n"
5042        | RStructList (n, typ) ->
5043            pr "struct %s_ret {\n" name;
5044            pr "  guestfs_int_%s_list %s;\n" typ n;
5045            pr "};\n\n"
5046        | RHashtable n ->
5047            pr "struct %s_ret {\n" name;
5048            pr "  str %s<>;\n" n;
5049            pr "};\n\n"
5050        | RBufferOut n ->
5051            pr "struct %s_ret {\n" name;
5052            pr "  opaque %s<>;\n" n;
5053            pr "};\n\n"
5054       );
5055   ) daemon_functions;
5056
5057   (* Table of procedure numbers. *)
5058   pr "enum guestfs_procedure {\n";
5059   List.iter (
5060     fun (shortname, _, proc_nr, _, _, _, _) ->
5061       pr "  GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
5062   ) daemon_functions;
5063   pr "  GUESTFS_PROC_NR_PROCS\n";
5064   pr "};\n";
5065   pr "\n";
5066
5067   (* Having to choose a maximum message size is annoying for several
5068    * reasons (it limits what we can do in the API), but it (a) makes
5069    * the protocol a lot simpler, and (b) provides a bound on the size
5070    * of the daemon which operates in limited memory space.  For large
5071    * file transfers you should use FTP.
5072    *)
5073   pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
5074   pr "\n";
5075
5076   (* Message header, etc. *)
5077   pr "\
5078 /* The communication protocol is now documented in the guestfs(3)
5079  * manpage.
5080  */
5081
5082 const GUESTFS_PROGRAM = 0x2000F5F5;
5083 const GUESTFS_PROTOCOL_VERSION = 1;
5084
5085 /* These constants must be larger than any possible message length. */
5086 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
5087 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
5088
5089 enum guestfs_message_direction {
5090   GUESTFS_DIRECTION_CALL = 0,        /* client -> daemon */
5091   GUESTFS_DIRECTION_REPLY = 1        /* daemon -> client */
5092 };
5093
5094 enum guestfs_message_status {
5095   GUESTFS_STATUS_OK = 0,
5096   GUESTFS_STATUS_ERROR = 1
5097 };
5098
5099 const GUESTFS_ERROR_LEN = 256;
5100
5101 struct guestfs_message_error {
5102   string error_message<GUESTFS_ERROR_LEN>;
5103 };
5104
5105 struct guestfs_message_header {
5106   unsigned prog;                     /* GUESTFS_PROGRAM */
5107   unsigned vers;                     /* GUESTFS_PROTOCOL_VERSION */
5108   guestfs_procedure proc;            /* GUESTFS_PROC_x */
5109   guestfs_message_direction direction;
5110   unsigned serial;                   /* message serial number */
5111   guestfs_message_status status;
5112 };
5113
5114 const GUESTFS_MAX_CHUNK_SIZE = 8192;
5115
5116 struct guestfs_chunk {
5117   int cancel;                        /* if non-zero, transfer is cancelled */
5118   /* data size is 0 bytes if the transfer has finished successfully */
5119   opaque data<GUESTFS_MAX_CHUNK_SIZE>;
5120 };
5121 "
5122
5123 (* Generate the guestfs-structs.h file. *)
5124 and generate_structs_h () =
5125   generate_header CStyle LGPLv2;
5126
5127   (* This is a public exported header file containing various
5128    * structures.  The structures are carefully written to have
5129    * exactly the same in-memory format as the XDR structures that
5130    * we use on the wire to the daemon.  The reason for creating
5131    * copies of these structures here is just so we don't have to
5132    * export the whole of guestfs_protocol.h (which includes much
5133    * unrelated and XDR-dependent stuff that we don't want to be
5134    * public, or required by clients).
5135    *
5136    * To reiterate, we will pass these structures to and from the
5137    * client with a simple assignment or memcpy, so the format
5138    * must be identical to what rpcgen / the RFC defines.
5139    *)
5140
5141   (* Public structures. *)
5142   List.iter (
5143     fun (typ, cols) ->
5144       pr "struct guestfs_%s {\n" typ;
5145       List.iter (
5146         function
5147         | name, FChar -> pr "  char %s;\n" name
5148         | name, FString -> pr "  char *%s;\n" name
5149         | name, FBuffer ->
5150             pr "  uint32_t %s_len;\n" name;
5151             pr "  char *%s;\n" name
5152         | name, FUUID -> pr "  char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
5153         | name, FUInt32 -> pr "  uint32_t %s;\n" name
5154         | name, FInt32 -> pr "  int32_t %s;\n" name
5155         | name, (FUInt64|FBytes) -> pr "  uint64_t %s;\n" name
5156         | name, FInt64 -> pr "  int64_t %s;\n" name
5157         | name, FOptPercent -> pr "  float %s; /* [0..100] or -1 */\n" name
5158       ) cols;
5159       pr "};\n";
5160       pr "\n";
5161       pr "struct guestfs_%s_list {\n" typ;
5162       pr "  uint32_t len;\n";
5163       pr "  struct guestfs_%s *val;\n" typ;
5164       pr "};\n";
5165       pr "\n";
5166       pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
5167       pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
5168       pr "\n"
5169   ) structs
5170
5171 (* Generate the guestfs-actions.h file. *)
5172 and generate_actions_h () =
5173   generate_header CStyle LGPLv2;
5174   List.iter (
5175     fun (shortname, style, _, _, _, _, _) ->
5176       let name = "guestfs_" ^ shortname in
5177       generate_prototype ~single_line:true ~newline:true ~handle:"handle"
5178         name style
5179   ) all_functions
5180
5181 (* Generate the guestfs-internal-actions.h file. *)
5182 and generate_internal_actions_h () =
5183   generate_header CStyle LGPLv2;
5184   List.iter (
5185     fun (shortname, style, _, _, _, _, _) ->
5186       let name = "guestfs__" ^ shortname in
5187       generate_prototype ~single_line:true ~newline:true ~handle:"handle"
5188         name style
5189   ) non_daemon_functions
5190
5191 (* Generate the client-side dispatch stubs. *)
5192 and generate_client_actions () =
5193   generate_header CStyle LGPLv2;
5194
5195   pr "\
5196 #include <stdio.h>
5197 #include <stdlib.h>
5198 #include <stdint.h>
5199 #include <inttypes.h>
5200
5201 #include \"guestfs.h\"
5202 #include \"guestfs-internal.h\"
5203 #include \"guestfs-internal-actions.h\"
5204 #include \"guestfs_protocol.h\"
5205
5206 #define error guestfs_error
5207 //#define perrorf guestfs_perrorf
5208 #define safe_malloc guestfs_safe_malloc
5209 #define safe_realloc guestfs_safe_realloc
5210 //#define safe_strdup guestfs_safe_strdup
5211 #define safe_memdup guestfs_safe_memdup
5212
5213 /* Check the return message from a call for validity. */
5214 static int
5215 check_reply_header (guestfs_h *g,
5216                     const struct guestfs_message_header *hdr,
5217                     unsigned int proc_nr, unsigned int serial)
5218 {
5219   if (hdr->prog != GUESTFS_PROGRAM) {
5220     error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
5221     return -1;
5222   }
5223   if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
5224     error (g, \"wrong protocol version (%%d/%%d)\",
5225            hdr->vers, GUESTFS_PROTOCOL_VERSION);
5226     return -1;
5227   }
5228   if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
5229     error (g, \"unexpected message direction (%%d/%%d)\",
5230            hdr->direction, GUESTFS_DIRECTION_REPLY);
5231     return -1;
5232   }
5233   if (hdr->proc != proc_nr) {
5234     error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
5235     return -1;
5236   }
5237   if (hdr->serial != serial) {
5238     error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
5239     return -1;
5240   }
5241
5242   return 0;
5243 }
5244
5245 /* Check we are in the right state to run a high-level action. */
5246 static int
5247 check_state (guestfs_h *g, const char *caller)
5248 {
5249   if (!guestfs__is_ready (g)) {
5250     if (guestfs__is_config (g) || guestfs__is_launching (g))
5251       error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
5252         caller);
5253     else
5254       error (g, \"%%s called from the wrong state, %%d != READY\",
5255         caller, guestfs__get_state (g));
5256     return -1;
5257   }
5258   return 0;
5259 }
5260
5261 ";
5262
5263   (* Generate code to generate guestfish call traces. *)
5264   let trace_call shortname style =
5265     pr "  if (guestfs__get_trace (g)) {\n";
5266
5267     let needs_i =
5268       List.exists (function
5269                    | StringList _ | DeviceList _ -> true
5270                    | _ -> false) (snd style) in
5271     if needs_i then (
5272       pr "    int i;\n";
5273       pr "\n"
5274     );
5275
5276     pr "    printf (\"%s\");\n" shortname;
5277     List.iter (
5278       function
5279       | String n                        (* strings *)
5280       | Device n
5281       | Pathname n
5282       | Dev_or_Path n
5283       | FileIn n
5284       | FileOut n ->
5285           (* guestfish doesn't support string escaping, so neither do we *)
5286           pr "    printf (\" \\\"%%s\\\"\", %s);\n" n
5287       | OptString n ->                  (* string option *)
5288           pr "    if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
5289           pr "    else printf (\" null\");\n"
5290       | StringList n
5291       | DeviceList n ->                 (* string list *)
5292           pr "    putchar (' ');\n";
5293           pr "    putchar ('\"');\n";
5294           pr "    for (i = 0; %s[i]; ++i) {\n" n;
5295           pr "      if (i > 0) putchar (' ');\n";
5296           pr "      fputs (%s[i], stdout);\n" n;
5297           pr "    }\n";
5298           pr "    putchar ('\"');\n";
5299       | Bool n ->                       (* boolean *)
5300           pr "    fputs (%s ? \" true\" : \" false\", stdout);\n" n
5301       | Int n ->                        (* int *)
5302           pr "    printf (\" %%d\", %s);\n" n
5303       | Int64 n ->
5304           pr "    printf (\" %%\" PRIi64, %s);\n" n
5305     ) (snd style);
5306     pr "    putchar ('\\n');\n";
5307     pr "  }\n";
5308     pr "\n";
5309   in
5310
5311   (* For non-daemon functions, generate a wrapper around each function. *)
5312   List.iter (
5313     fun (shortname, style, _, _, _, _, _) ->
5314       let name = "guestfs_" ^ shortname in
5315
5316       generate_prototype ~extern:false ~semicolon:false ~newline:true
5317         ~handle:"g" name style;
5318       pr "{\n";
5319       trace_call shortname style;
5320       pr "  return guestfs__%s " shortname;
5321       generate_c_call_args ~handle:"g" style;
5322       pr ";\n";
5323       pr "}\n";
5324       pr "\n"
5325   ) non_daemon_functions;
5326
5327   (* Client-side stubs for each function. *)
5328   List.iter (
5329     fun (shortname, style, _, _, _, _, _) ->
5330       let name = "guestfs_" ^ shortname in
5331
5332       (* Generate the action stub. *)
5333       generate_prototype ~extern:false ~semicolon:false ~newline:true
5334         ~handle:"g" name style;
5335
5336       let error_code =
5337         match fst style with
5338         | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
5339         | RConstString _ | RConstOptString _ ->
5340             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5341         | RString _ | RStringList _
5342         | RStruct _ | RStructList _
5343         | RHashtable _ | RBufferOut _ ->
5344             "NULL" in
5345
5346       pr "{\n";
5347
5348       (match snd style with
5349        | [] -> ()
5350        | _ -> pr "  struct %s_args args;\n" name
5351       );
5352
5353       pr "  guestfs_message_header hdr;\n";
5354       pr "  guestfs_message_error err;\n";
5355       let has_ret =
5356         match fst style with
5357         | RErr -> false
5358         | RConstString _ | RConstOptString _ ->
5359             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5360         | RInt _ | RInt64 _
5361         | RBool _ | RString _ | RStringList _
5362         | RStruct _ | RStructList _
5363         | RHashtable _ | RBufferOut _ ->
5364             pr "  struct %s_ret ret;\n" name;
5365             true in
5366
5367       pr "  int serial;\n";
5368       pr "  int r;\n";
5369       pr "\n";
5370       trace_call shortname style;
5371       pr "  if (check_state (g, \"%s\") == -1) return %s;\n" name error_code;
5372       pr "  guestfs___set_busy (g);\n";
5373       pr "\n";
5374
5375       (* Send the main header and arguments. *)
5376       (match snd style with
5377        | [] ->
5378            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
5379              (String.uppercase shortname)
5380        | args ->
5381            List.iter (
5382              function
5383              | Pathname n | Device n | Dev_or_Path n | String n ->
5384                  pr "  args.%s = (char *) %s;\n" n n
5385              | OptString n ->
5386                  pr "  args.%s = %s ? (char **) &%s : NULL;\n" n n n
5387              | StringList n | DeviceList n ->
5388                  pr "  args.%s.%s_val = (char **) %s;\n" n n n;
5389                  pr "  for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
5390              | Bool n ->
5391                  pr "  args.%s = %s;\n" n n
5392              | Int n ->
5393                  pr "  args.%s = %s;\n" n n
5394              | Int64 n ->
5395                  pr "  args.%s = %s;\n" n n
5396              | FileIn _ | FileOut _ -> ()
5397            ) args;
5398            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
5399              (String.uppercase shortname);
5400            pr "        (xdrproc_t) xdr_%s_args, (char *) &args);\n"
5401              name;
5402       );
5403       pr "  if (serial == -1) {\n";
5404       pr "    guestfs___end_busy (g);\n";
5405       pr "    return %s;\n" error_code;
5406       pr "  }\n";
5407       pr "\n";
5408
5409       (* Send any additional files (FileIn) requested. *)
5410       let need_read_reply_label = ref false in
5411       List.iter (
5412         function
5413         | FileIn n ->
5414             pr "  r = guestfs___send_file (g, %s);\n" n;
5415             pr "  if (r == -1) {\n";
5416             pr "    guestfs___end_busy (g);\n";
5417             pr "    return %s;\n" error_code;
5418             pr "  }\n";
5419             pr "  if (r == -2) /* daemon cancelled */\n";
5420             pr "    goto read_reply;\n";
5421             need_read_reply_label := true;
5422             pr "\n";
5423         | _ -> ()
5424       ) (snd style);
5425
5426       (* Wait for the reply from the remote end. *)
5427       if !need_read_reply_label then pr " read_reply:\n";
5428       pr "  memset (&hdr, 0, sizeof hdr);\n";
5429       pr "  memset (&err, 0, sizeof err);\n";
5430       if has_ret then pr "  memset (&ret, 0, sizeof ret);\n";
5431       pr "\n";
5432       pr "  r = guestfs___recv (g, \"%s\", &hdr, &err,\n        " shortname;
5433       if not has_ret then
5434         pr "NULL, NULL"
5435       else
5436         pr "(xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret" shortname;
5437       pr ");\n";
5438
5439       pr "  if (r == -1) {\n";
5440       pr "    guestfs___end_busy (g);\n";
5441       pr "    return %s;\n" error_code;
5442       pr "  }\n";
5443       pr "\n";
5444
5445       pr "  if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
5446         (String.uppercase shortname);
5447       pr "    guestfs___end_busy (g);\n";
5448       pr "    return %s;\n" error_code;
5449       pr "  }\n";
5450       pr "\n";
5451
5452       pr "  if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
5453       pr "    error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
5454       pr "    free (err.error_message);\n";
5455       pr "    guestfs___end_busy (g);\n";
5456       pr "    return %s;\n" error_code;
5457       pr "  }\n";
5458       pr "\n";
5459
5460       (* Expecting to receive further files (FileOut)? *)
5461       List.iter (
5462         function
5463         | FileOut n ->
5464             pr "  if (guestfs___recv_file (g, %s) == -1) {\n" n;
5465             pr "    guestfs___end_busy (g);\n";
5466             pr "    return %s;\n" error_code;
5467             pr "  }\n";
5468             pr "\n";
5469         | _ -> ()
5470       ) (snd style);
5471
5472       pr "  guestfs___end_busy (g);\n";
5473
5474       (match fst style with
5475        | RErr -> pr "  return 0;\n"
5476        | RInt n | RInt64 n | RBool n ->
5477            pr "  return ret.%s;\n" n
5478        | RConstString _ | RConstOptString _ ->
5479            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5480        | RString n ->
5481            pr "  return ret.%s; /* caller will free */\n" n
5482        | RStringList n | RHashtable n ->
5483            pr "  /* caller will free this, but we need to add a NULL entry */\n";
5484            pr "  ret.%s.%s_val =\n" n n;
5485            pr "    safe_realloc (g, ret.%s.%s_val,\n" n n;
5486            pr "                  sizeof (char *) * (ret.%s.%s_len + 1));\n"
5487              n n;
5488            pr "  ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
5489            pr "  return ret.%s.%s_val;\n" n n
5490        | RStruct (n, _) ->
5491            pr "  /* caller will free this */\n";
5492            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5493        | RStructList (n, _) ->
5494            pr "  /* caller will free this */\n";
5495            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5496        | RBufferOut n ->
5497            pr "  /* RBufferOut is tricky: If the buffer is zero-length, then\n";
5498            pr "   * _val might be NULL here.  To make the API saner for\n";
5499            pr "   * callers, we turn this case into a unique pointer (using\n";
5500            pr "   * malloc(1)).\n";
5501            pr "   */\n";
5502            pr "  if (ret.%s.%s_len > 0) {\n" n n;
5503            pr "    *size_r = ret.%s.%s_len;\n" n n;
5504            pr "    return ret.%s.%s_val; /* caller will free */\n" n n;
5505            pr "  } else {\n";
5506            pr "    free (ret.%s.%s_val);\n" n n;
5507            pr "    char *p = safe_malloc (g, 1);\n";
5508            pr "    *size_r = ret.%s.%s_len;\n" n n;
5509            pr "    return p;\n";
5510            pr "  }\n";
5511       );
5512
5513       pr "}\n\n"
5514   ) daemon_functions;
5515
5516   (* Functions to free structures. *)
5517   pr "/* Structure-freeing functions.  These rely on the fact that the\n";
5518   pr " * structure format is identical to the XDR format.  See note in\n";
5519   pr " * generator.ml.\n";
5520   pr " */\n";
5521   pr "\n";
5522
5523   List.iter (
5524     fun (typ, _) ->
5525       pr "void\n";
5526       pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
5527       pr "{\n";
5528       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
5529       pr "  free (x);\n";
5530       pr "}\n";
5531       pr "\n";
5532
5533       pr "void\n";
5534       pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
5535       pr "{\n";
5536       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
5537       pr "  free (x);\n";
5538       pr "}\n";
5539       pr "\n";
5540
5541   ) structs;
5542
5543 (* Generate daemon/actions.h. *)
5544 and generate_daemon_actions_h () =
5545   generate_header CStyle GPLv2;
5546
5547   pr "#include \"../src/guestfs_protocol.h\"\n";
5548   pr "\n";
5549
5550   List.iter (
5551     fun (name, style, _, _, _, _, _) ->
5552       generate_prototype
5553         ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
5554         name style;
5555   ) daemon_functions
5556
5557 (* Generate the server-side stubs. *)
5558 and generate_daemon_actions () =
5559   generate_header CStyle GPLv2;
5560
5561   pr "#include <config.h>\n";
5562   pr "\n";
5563   pr "#include <stdio.h>\n";
5564   pr "#include <stdlib.h>\n";
5565   pr "#include <string.h>\n";
5566   pr "#include <inttypes.h>\n";
5567   pr "#include <rpc/types.h>\n";
5568   pr "#include <rpc/xdr.h>\n";
5569   pr "\n";
5570   pr "#include \"daemon.h\"\n";
5571   pr "#include \"c-ctype.h\"\n";
5572   pr "#include \"../src/guestfs_protocol.h\"\n";
5573   pr "#include \"actions.h\"\n";
5574   pr "\n";
5575
5576   List.iter (
5577     fun (name, style, _, _, _, _, _) ->
5578       (* Generate server-side stubs. *)
5579       pr "static void %s_stub (XDR *xdr_in)\n" name;
5580       pr "{\n";
5581       let error_code =
5582         match fst style with
5583         | RErr | RInt _ -> pr "  int r;\n"; "-1"
5584         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
5585         | RBool _ -> pr "  int r;\n"; "-1"
5586         | RConstString _ | RConstOptString _ ->
5587             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5588         | RString _ -> pr "  char *r;\n"; "NULL"
5589         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
5590         | RStruct (_, typ) -> pr "  guestfs_int_%s *r;\n" typ; "NULL"
5591         | RStructList (_, typ) -> pr "  guestfs_int_%s_list *r;\n" typ; "NULL"
5592         | RBufferOut _ ->
5593             pr "  size_t size = 1;\n";
5594             pr "  char *r;\n";
5595             "NULL" in
5596
5597       (match snd style with
5598        | [] -> ()
5599        | args ->
5600            pr "  struct guestfs_%s_args args;\n" name;
5601            List.iter (
5602              function
5603              | Device n | Dev_or_Path n
5604              | Pathname n
5605              | String n -> ()
5606              | OptString n -> pr "  char *%s;\n" n
5607              | StringList n | DeviceList n -> pr "  char **%s;\n" n
5608              | Bool n -> pr "  int %s;\n" n
5609              | Int n -> pr "  int %s;\n" n
5610              | Int64 n -> pr "  int64_t %s;\n" n
5611              | FileIn _ | FileOut _ -> ()
5612            ) args
5613       );
5614       pr "\n";
5615
5616       (match snd style with
5617        | [] -> ()
5618        | args ->
5619            pr "  memset (&args, 0, sizeof args);\n";
5620            pr "\n";
5621            pr "  if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
5622            pr "    reply_with_error (\"%%s: daemon failed to decode procedure arguments\", \"%s\");\n" name;
5623            pr "    return;\n";
5624            pr "  }\n";
5625            let pr_args n =
5626              pr "  char *%s = args.%s;\n" n n
5627            in
5628            let pr_list_handling_code n =
5629              pr "  %s = realloc (args.%s.%s_val,\n" n n n;
5630              pr "                sizeof (char *) * (args.%s.%s_len+1));\n" n n;
5631              pr "  if (%s == NULL) {\n" n;
5632              pr "    reply_with_perror (\"realloc\");\n";
5633              pr "    goto done;\n";
5634              pr "  }\n";
5635              pr "  %s[args.%s.%s_len] = NULL;\n" n n n;
5636              pr "  args.%s.%s_val = %s;\n" n n n;
5637            in
5638            List.iter (
5639              function
5640              | Pathname n ->
5641                  pr_args n;
5642                  pr "  ABS_PATH (%s, goto done);\n" n;
5643              | Device n ->
5644                  pr_args n;
5645                  pr "  RESOLVE_DEVICE (%s, goto done);\n" n;
5646              | Dev_or_Path n ->
5647                  pr_args n;
5648                  pr "  REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, goto done);\n" n;
5649              | String n -> pr_args n
5650              | OptString n -> pr "  %s = args.%s ? *args.%s : NULL;\n" n n n
5651              | StringList n ->
5652                  pr_list_handling_code n;
5653              | DeviceList n ->
5654                  pr_list_handling_code n;
5655                  pr "  /* Ensure that each is a device,\n";
5656                  pr "   * and perform device name translation. */\n";
5657                  pr "  { int pvi; for (pvi = 0; physvols[pvi] != NULL; ++pvi)\n";
5658                  pr "    RESOLVE_DEVICE (physvols[pvi], goto done);\n";
5659                  pr "  }\n";
5660              | Bool n -> pr "  %s = args.%s;\n" n n
5661              | Int n -> pr "  %s = args.%s;\n" n n
5662              | Int64 n -> pr "  %s = args.%s;\n" n n
5663              | FileIn _ | FileOut _ -> ()
5664            ) args;
5665            pr "\n"
5666       );
5667
5668
5669       (* this is used at least for do_equal *)
5670       if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
5671         (* Emit NEED_ROOT just once, even when there are two or
5672            more Pathname args *)
5673         pr "  NEED_ROOT (goto done);\n";
5674       );
5675
5676       (* Don't want to call the impl with any FileIn or FileOut
5677        * parameters, since these go "outside" the RPC protocol.
5678        *)
5679       let args' =
5680         List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
5681           (snd style) in
5682       pr "  r = do_%s " name;
5683       generate_c_call_args (fst style, args');
5684       pr ";\n";
5685
5686       (match fst style with
5687        | RErr | RInt _ | RInt64 _ | RBool _
5688        | RConstString _ | RConstOptString _
5689        | RString _ | RStringList _ | RHashtable _
5690        | RStruct (_, _) | RStructList (_, _) ->
5691            pr "  if (r == %s)\n" error_code;
5692            pr "    /* do_%s has already called reply_with_error */\n" name;
5693            pr "    goto done;\n";
5694            pr "\n"
5695        | RBufferOut _ ->
5696            pr "  /* size == 0 && r == NULL could be a non-error case (just\n";
5697            pr "   * an ordinary zero-length buffer), so be careful ...\n";
5698            pr "   */\n";
5699            pr "  if (size == 1 && r == %s)\n" error_code;
5700            pr "    /* do_%s has already called reply_with_error */\n" name;
5701            pr "    goto done;\n";
5702            pr "\n"
5703       );
5704
5705       (* If there are any FileOut parameters, then the impl must
5706        * send its own reply.
5707        *)
5708       let no_reply =
5709         List.exists (function FileOut _ -> true | _ -> false) (snd style) in
5710       if no_reply then
5711         pr "  /* do_%s has already sent a reply */\n" name
5712       else (
5713         match fst style with
5714         | RErr -> pr "  reply (NULL, NULL);\n"
5715         | RInt n | RInt64 n | RBool n ->
5716             pr "  struct guestfs_%s_ret ret;\n" name;
5717             pr "  ret.%s = r;\n" n;
5718             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5719               name
5720         | RConstString _ | RConstOptString _ ->
5721             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5722         | RString n ->
5723             pr "  struct guestfs_%s_ret ret;\n" name;
5724             pr "  ret.%s = r;\n" n;
5725             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5726               name;
5727             pr "  free (r);\n"
5728         | RStringList n | RHashtable n ->
5729             pr "  struct guestfs_%s_ret ret;\n" name;
5730             pr "  ret.%s.%s_len = count_strings (r);\n" n n;
5731             pr "  ret.%s.%s_val = r;\n" n n;
5732             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5733               name;
5734             pr "  free_strings (r);\n"
5735         | RStruct (n, _) ->
5736             pr "  struct guestfs_%s_ret ret;\n" name;
5737             pr "  ret.%s = *r;\n" n;
5738             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5739               name;
5740             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5741               name
5742         | RStructList (n, _) ->
5743             pr "  struct guestfs_%s_ret ret;\n" name;
5744             pr "  ret.%s = *r;\n" n;
5745             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5746               name;
5747             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5748               name
5749         | RBufferOut n ->
5750             pr "  struct guestfs_%s_ret ret;\n" name;
5751             pr "  ret.%s.%s_val = r;\n" n n;
5752             pr "  ret.%s.%s_len = size;\n" n n;
5753             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5754               name;
5755             pr "  free (r);\n"
5756       );
5757
5758       (* Free the args. *)
5759       (match snd style with
5760        | [] ->
5761            pr "done: ;\n";
5762        | _ ->
5763            pr "done:\n";
5764            pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
5765              name
5766       );
5767
5768       pr "}\n\n";
5769   ) daemon_functions;
5770
5771   (* Dispatch function. *)
5772   pr "void dispatch_incoming_message (XDR *xdr_in)\n";
5773   pr "{\n";
5774   pr "  switch (proc_nr) {\n";
5775
5776   List.iter (
5777     fun (name, style, _, _, _, _, _) ->
5778       pr "    case GUESTFS_PROC_%s:\n" (String.uppercase name);
5779       pr "      %s_stub (xdr_in);\n" name;
5780       pr "      break;\n"
5781   ) daemon_functions;
5782
5783   pr "    default:\n";
5784   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";
5785   pr "  }\n";
5786   pr "}\n";
5787   pr "\n";
5788
5789   (* LVM columns and tokenization functions. *)
5790   (* XXX This generates crap code.  We should rethink how we
5791    * do this parsing.
5792    *)
5793   List.iter (
5794     function
5795     | typ, cols ->
5796         pr "static const char *lvm_%s_cols = \"%s\";\n"
5797           typ (String.concat "," (List.map fst cols));
5798         pr "\n";
5799
5800         pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
5801         pr "{\n";
5802         pr "  char *tok, *p, *next;\n";
5803         pr "  int i, j;\n";
5804         pr "\n";
5805         (*
5806           pr "  fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
5807           pr "\n";
5808         *)
5809         pr "  if (!str) {\n";
5810         pr "    fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
5811         pr "    return -1;\n";
5812         pr "  }\n";
5813         pr "  if (!*str || c_isspace (*str)) {\n";
5814         pr "    fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
5815         pr "    return -1;\n";
5816         pr "  }\n";
5817         pr "  tok = str;\n";
5818         List.iter (
5819           fun (name, coltype) ->
5820             pr "  if (!tok) {\n";
5821             pr "    fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
5822             pr "    return -1;\n";
5823             pr "  }\n";
5824             pr "  p = strchrnul (tok, ',');\n";
5825             pr "  if (*p) next = p+1; else next = NULL;\n";
5826             pr "  *p = '\\0';\n";
5827             (match coltype with
5828              | FString ->
5829                  pr "  r->%s = strdup (tok);\n" name;
5830                  pr "  if (r->%s == NULL) {\n" name;
5831                  pr "    perror (\"strdup\");\n";
5832                  pr "    return -1;\n";
5833                  pr "  }\n"
5834              | FUUID ->
5835                  pr "  for (i = j = 0; i < 32; ++j) {\n";
5836                  pr "    if (tok[j] == '\\0') {\n";
5837                  pr "      fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
5838                  pr "      return -1;\n";
5839                  pr "    } else if (tok[j] != '-')\n";
5840                  pr "      r->%s[i++] = tok[j];\n" name;
5841                  pr "  }\n";
5842              | FBytes ->
5843                  pr "  if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
5844                  pr "    fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
5845                  pr "    return -1;\n";
5846                  pr "  }\n";
5847              | FInt64 ->
5848                  pr "  if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
5849                  pr "    fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
5850                  pr "    return -1;\n";
5851                  pr "  }\n";
5852              | FOptPercent ->
5853                  pr "  if (tok[0] == '\\0')\n";
5854                  pr "    r->%s = -1;\n" name;
5855                  pr "  else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
5856                  pr "    fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
5857                  pr "    return -1;\n";
5858                  pr "  }\n";
5859              | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
5860                  assert false (* can never be an LVM column *)
5861             );
5862             pr "  tok = next;\n";
5863         ) cols;
5864
5865         pr "  if (tok != NULL) {\n";
5866         pr "    fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
5867         pr "    return -1;\n";
5868         pr "  }\n";
5869         pr "  return 0;\n";
5870         pr "}\n";
5871         pr "\n";
5872
5873         pr "guestfs_int_lvm_%s_list *\n" typ;
5874         pr "parse_command_line_%ss (void)\n" typ;
5875         pr "{\n";
5876         pr "  char *out, *err;\n";
5877         pr "  char *p, *pend;\n";
5878         pr "  int r, i;\n";
5879         pr "  guestfs_int_lvm_%s_list *ret;\n" typ;
5880         pr "  void *newp;\n";
5881         pr "\n";
5882         pr "  ret = malloc (sizeof *ret);\n";
5883         pr "  if (!ret) {\n";
5884         pr "    reply_with_perror (\"malloc\");\n";
5885         pr "    return NULL;\n";
5886         pr "  }\n";
5887         pr "\n";
5888         pr "  ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
5889         pr "  ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
5890         pr "\n";
5891         pr "  r = command (&out, &err,\n";
5892         pr "           \"/sbin/lvm\", \"%ss\",\n" typ;
5893         pr "           \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
5894         pr "           \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
5895         pr "  if (r == -1) {\n";
5896         pr "    reply_with_error (\"%%s\", err);\n";
5897         pr "    free (out);\n";
5898         pr "    free (err);\n";
5899         pr "    free (ret);\n";
5900         pr "    return NULL;\n";
5901         pr "  }\n";
5902         pr "\n";
5903         pr "  free (err);\n";
5904         pr "\n";
5905         pr "  /* Tokenize each line of the output. */\n";
5906         pr "  p = out;\n";
5907         pr "  i = 0;\n";
5908         pr "  while (p) {\n";
5909         pr "    pend = strchr (p, '\\n');       /* Get the next line of output. */\n";
5910         pr "    if (pend) {\n";
5911         pr "      *pend = '\\0';\n";
5912         pr "      pend++;\n";
5913         pr "    }\n";
5914         pr "\n";
5915         pr "    while (*p && c_isspace (*p))    /* Skip any leading whitespace. */\n";
5916         pr "      p++;\n";
5917         pr "\n";
5918         pr "    if (!*p) {                      /* Empty line?  Skip it. */\n";
5919         pr "      p = pend;\n";
5920         pr "      continue;\n";
5921         pr "    }\n";
5922         pr "\n";
5923         pr "    /* Allocate some space to store this next entry. */\n";
5924         pr "    newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
5925         pr "                sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
5926         pr "    if (newp == NULL) {\n";
5927         pr "      reply_with_perror (\"realloc\");\n";
5928         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
5929         pr "      free (ret);\n";
5930         pr "      free (out);\n";
5931         pr "      return NULL;\n";
5932         pr "    }\n";
5933         pr "    ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
5934         pr "\n";
5935         pr "    /* Tokenize the next entry. */\n";
5936         pr "    r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
5937         pr "    if (r == -1) {\n";
5938         pr "      reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
5939         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
5940         pr "      free (ret);\n";
5941         pr "      free (out);\n";
5942         pr "      return NULL;\n";
5943         pr "    }\n";
5944         pr "\n";
5945         pr "    ++i;\n";
5946         pr "    p = pend;\n";
5947         pr "  }\n";
5948         pr "\n";
5949         pr "  ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
5950         pr "\n";
5951         pr "  free (out);\n";
5952         pr "  return ret;\n";
5953         pr "}\n"
5954
5955   ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
5956
5957 (* Generate a list of function names, for debugging in the daemon.. *)
5958 and generate_daemon_names () =
5959   generate_header CStyle GPLv2;
5960
5961   pr "#include <config.h>\n";
5962   pr "\n";
5963   pr "#include \"daemon.h\"\n";
5964   pr "\n";
5965
5966   pr "/* This array is indexed by proc_nr.  See guestfs_protocol.x. */\n";
5967   pr "const char *function_names[] = {\n";
5968   List.iter (
5969     fun (name, _, proc_nr, _, _, _, _) -> pr "  [%d] = \"%s\",\n" proc_nr name
5970   ) daemon_functions;
5971   pr "};\n";
5972
5973 (* Generate the optional groups for the daemon to implement
5974  * guestfs_available.
5975  *)
5976 and generate_daemon_optgroups_c () =
5977   generate_header CStyle GPLv2;
5978
5979   pr "#include <config.h>\n";
5980   pr "\n";
5981   pr "#include \"daemon.h\"\n";
5982   pr "#include \"optgroups.h\"\n";
5983   pr "\n";
5984
5985   pr "struct optgroup optgroups[] = {\n";
5986   List.iter (
5987     fun (group, _) ->
5988       pr "  { \"%s\", optgroup_%s_available },\n" group group
5989   ) optgroups;
5990   pr "  { NULL, NULL }\n";
5991   pr "};\n"
5992
5993 and generate_daemon_optgroups_h () =
5994   generate_header CStyle GPLv2;
5995
5996   List.iter (
5997     fun (group, _) ->
5998       pr "extern int optgroup_%s_available (void);\n" group
5999   ) optgroups
6000
6001 (* Generate the tests. *)
6002 and generate_tests () =
6003   generate_header CStyle GPLv2;
6004
6005   pr "\
6006 #include <stdio.h>
6007 #include <stdlib.h>
6008 #include <string.h>
6009 #include <unistd.h>
6010 #include <sys/types.h>
6011 #include <fcntl.h>
6012
6013 #include \"guestfs.h\"
6014 #include \"guestfs-internal.h\"
6015
6016 static guestfs_h *g;
6017 static int suppress_error = 0;
6018
6019 static void print_error (guestfs_h *g, void *data, const char *msg)
6020 {
6021   if (!suppress_error)
6022     fprintf (stderr, \"%%s\\n\", msg);
6023 }
6024
6025 /* FIXME: nearly identical code appears in fish.c */
6026 static void print_strings (char *const *argv)
6027 {
6028   int argc;
6029
6030   for (argc = 0; argv[argc] != NULL; ++argc)
6031     printf (\"\\t%%s\\n\", argv[argc]);
6032 }
6033
6034 /*
6035 static void print_table (char const *const *argv)
6036 {
6037   int i;
6038
6039   for (i = 0; argv[i] != NULL; i += 2)
6040     printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
6041 }
6042 */
6043
6044 ";
6045
6046   (* Generate a list of commands which are not tested anywhere. *)
6047   pr "static void no_test_warnings (void)\n";
6048   pr "{\n";
6049
6050   let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
6051   List.iter (
6052     fun (_, _, _, _, tests, _, _) ->
6053       let tests = filter_map (
6054         function
6055         | (_, (Always|If _|Unless _), test) -> Some test
6056         | (_, Disabled, _) -> None
6057       ) tests in
6058       let seq = List.concat (List.map seq_of_test tests) in
6059       let cmds_tested = List.map List.hd seq in
6060       List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
6061   ) all_functions;
6062
6063   List.iter (
6064     fun (name, _, _, _, _, _, _) ->
6065       if not (Hashtbl.mem hash name) then
6066         pr "  fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
6067   ) all_functions;
6068
6069   pr "}\n";
6070   pr "\n";
6071
6072   (* Generate the actual tests.  Note that we generate the tests
6073    * in reverse order, deliberately, so that (in general) the
6074    * newest tests run first.  This makes it quicker and easier to
6075    * debug them.
6076    *)
6077   let test_names =
6078     List.map (
6079       fun (name, _, _, flags, tests, _, _) ->
6080         mapi (generate_one_test name flags) tests
6081     ) (List.rev all_functions) in
6082   let test_names = List.concat test_names in
6083   let nr_tests = List.length test_names in
6084
6085   pr "\
6086 int main (int argc, char *argv[])
6087 {
6088   char c = 0;
6089   unsigned long int n_failed = 0;
6090   const char *filename;
6091   int fd;
6092   int nr_tests, test_num = 0;
6093
6094   setbuf (stdout, NULL);
6095
6096   no_test_warnings ();
6097
6098   g = guestfs_create ();
6099   if (g == NULL) {
6100     printf (\"guestfs_create FAILED\\n\");
6101     exit (EXIT_FAILURE);
6102   }
6103
6104   guestfs_set_error_handler (g, print_error, NULL);
6105
6106   guestfs_set_path (g, \"../appliance\");
6107
6108   filename = \"test1.img\";
6109   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6110   if (fd == -1) {
6111     perror (filename);
6112     exit (EXIT_FAILURE);
6113   }
6114   if (lseek (fd, %d, SEEK_SET) == -1) {
6115     perror (\"lseek\");
6116     close (fd);
6117     unlink (filename);
6118     exit (EXIT_FAILURE);
6119   }
6120   if (write (fd, &c, 1) == -1) {
6121     perror (\"write\");
6122     close (fd);
6123     unlink (filename);
6124     exit (EXIT_FAILURE);
6125   }
6126   if (close (fd) == -1) {
6127     perror (filename);
6128     unlink (filename);
6129     exit (EXIT_FAILURE);
6130   }
6131   if (guestfs_add_drive (g, filename) == -1) {
6132     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6133     exit (EXIT_FAILURE);
6134   }
6135
6136   filename = \"test2.img\";
6137   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6138   if (fd == -1) {
6139     perror (filename);
6140     exit (EXIT_FAILURE);
6141   }
6142   if (lseek (fd, %d, SEEK_SET) == -1) {
6143     perror (\"lseek\");
6144     close (fd);
6145     unlink (filename);
6146     exit (EXIT_FAILURE);
6147   }
6148   if (write (fd, &c, 1) == -1) {
6149     perror (\"write\");
6150     close (fd);
6151     unlink (filename);
6152     exit (EXIT_FAILURE);
6153   }
6154   if (close (fd) == -1) {
6155     perror (filename);
6156     unlink (filename);
6157     exit (EXIT_FAILURE);
6158   }
6159   if (guestfs_add_drive (g, filename) == -1) {
6160     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6161     exit (EXIT_FAILURE);
6162   }
6163
6164   filename = \"test3.img\";
6165   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6166   if (fd == -1) {
6167     perror (filename);
6168     exit (EXIT_FAILURE);
6169   }
6170   if (lseek (fd, %d, SEEK_SET) == -1) {
6171     perror (\"lseek\");
6172     close (fd);
6173     unlink (filename);
6174     exit (EXIT_FAILURE);
6175   }
6176   if (write (fd, &c, 1) == -1) {
6177     perror (\"write\");
6178     close (fd);
6179     unlink (filename);
6180     exit (EXIT_FAILURE);
6181   }
6182   if (close (fd) == -1) {
6183     perror (filename);
6184     unlink (filename);
6185     exit (EXIT_FAILURE);
6186   }
6187   if (guestfs_add_drive (g, filename) == -1) {
6188     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6189     exit (EXIT_FAILURE);
6190   }
6191
6192   if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
6193     printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
6194     exit (EXIT_FAILURE);
6195   }
6196
6197   if (guestfs_launch (g) == -1) {
6198     printf (\"guestfs_launch FAILED\\n\");
6199     exit (EXIT_FAILURE);
6200   }
6201
6202   /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
6203   alarm (600);
6204
6205   /* Cancel previous alarm. */
6206   alarm (0);
6207
6208   nr_tests = %d;
6209
6210 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
6211
6212   iteri (
6213     fun i test_name ->
6214       pr "  test_num++;\n";
6215       pr "  printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
6216       pr "  if (%s () == -1) {\n" test_name;
6217       pr "    printf (\"%s FAILED\\n\");\n" test_name;
6218       pr "    n_failed++;\n";
6219       pr "  }\n";
6220   ) test_names;
6221   pr "\n";
6222
6223   pr "  guestfs_close (g);\n";
6224   pr "  unlink (\"test1.img\");\n";
6225   pr "  unlink (\"test2.img\");\n";
6226   pr "  unlink (\"test3.img\");\n";
6227   pr "\n";
6228
6229   pr "  if (n_failed > 0) {\n";
6230   pr "    printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
6231   pr "    exit (EXIT_FAILURE);\n";
6232   pr "  }\n";
6233   pr "\n";
6234
6235   pr "  exit (EXIT_SUCCESS);\n";
6236   pr "}\n"
6237
6238 and generate_one_test name flags i (init, prereq, test) =
6239   let test_name = sprintf "test_%s_%d" name i in
6240
6241   pr "\
6242 static int %s_skip (void)
6243 {
6244   const char *str;
6245
6246   str = getenv (\"TEST_ONLY\");
6247   if (str)
6248     return strstr (str, \"%s\") == NULL;
6249   str = getenv (\"SKIP_%s\");
6250   if (str && STREQ (str, \"1\")) return 1;
6251   str = getenv (\"SKIP_TEST_%s\");
6252   if (str && STREQ (str, \"1\")) return 1;
6253   return 0;
6254 }
6255
6256 " test_name name (String.uppercase test_name) (String.uppercase name);
6257
6258   (match prereq with
6259    | Disabled | Always -> ()
6260    | If code | Unless code ->
6261        pr "static int %s_prereq (void)\n" test_name;
6262        pr "{\n";
6263        pr "  %s\n" code;
6264        pr "}\n";
6265        pr "\n";
6266   );
6267
6268   pr "\
6269 static int %s (void)
6270 {
6271   if (%s_skip ()) {
6272     printf (\"        %%s skipped (reason: environment variable set)\\n\", \"%s\");
6273     return 0;
6274   }
6275
6276 " test_name test_name test_name;
6277
6278   (* Optional functions should only be tested if the relevant
6279    * support is available in the daemon.
6280    *)
6281   List.iter (
6282     function
6283     | Optional group ->
6284         pr "  {\n";
6285         pr "    const char *groups[] = { \"%s\", NULL };\n" group;
6286         pr "    int r;\n";
6287         pr "    suppress_error = 1;\n";
6288         pr "    r = guestfs_available (g, (char **) groups);\n";
6289         pr "    suppress_error = 0;\n";
6290         pr "    if (r == -1) {\n";
6291         pr "      printf (\"        %%s skipped (reason: group %%s not available in daemon)\\n\", \"%s\", groups[0]);\n" test_name;
6292         pr "      return 0;\n";
6293         pr "    }\n";
6294         pr "  }\n";
6295     | _ -> ()
6296   ) flags;
6297
6298   (match prereq with
6299    | Disabled ->
6300        pr "  printf (\"        %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
6301    | If _ ->
6302        pr "  if (! %s_prereq ()) {\n" test_name;
6303        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6304        pr "    return 0;\n";
6305        pr "  }\n";
6306        pr "\n";
6307        generate_one_test_body name i test_name init test;
6308    | Unless _ ->
6309        pr "  if (%s_prereq ()) {\n" test_name;
6310        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6311        pr "    return 0;\n";
6312        pr "  }\n";
6313        pr "\n";
6314        generate_one_test_body name i test_name init test;
6315    | Always ->
6316        generate_one_test_body name i test_name init test
6317   );
6318
6319   pr "  return 0;\n";
6320   pr "}\n";
6321   pr "\n";
6322   test_name
6323
6324 and generate_one_test_body name i test_name init test =
6325   (match init with
6326    | InitNone (* XXX at some point, InitNone and InitEmpty became
6327                * folded together as the same thing.  Really we should
6328                * make InitNone do nothing at all, but the tests may
6329                * need to be checked to make sure this is OK.
6330                *)
6331    | InitEmpty ->
6332        pr "  /* InitNone|InitEmpty for %s */\n" test_name;
6333        List.iter (generate_test_command_call test_name)
6334          [["blockdev_setrw"; "/dev/sda"];
6335           ["umount_all"];
6336           ["lvm_remove_all"]]
6337    | InitPartition ->
6338        pr "  /* InitPartition for %s: create /dev/sda1 */\n" test_name;
6339        List.iter (generate_test_command_call test_name)
6340          [["blockdev_setrw"; "/dev/sda"];
6341           ["umount_all"];
6342           ["lvm_remove_all"];
6343           ["part_disk"; "/dev/sda"; "mbr"]]
6344    | InitBasicFS ->
6345        pr "  /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
6346        List.iter (generate_test_command_call test_name)
6347          [["blockdev_setrw"; "/dev/sda"];
6348           ["umount_all"];
6349           ["lvm_remove_all"];
6350           ["part_disk"; "/dev/sda"; "mbr"];
6351           ["mkfs"; "ext2"; "/dev/sda1"];
6352           ["mount"; "/dev/sda1"; "/"]]
6353    | InitBasicFSonLVM ->
6354        pr "  /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
6355          test_name;
6356        List.iter (generate_test_command_call test_name)
6357          [["blockdev_setrw"; "/dev/sda"];
6358           ["umount_all"];
6359           ["lvm_remove_all"];
6360           ["part_disk"; "/dev/sda"; "mbr"];
6361           ["pvcreate"; "/dev/sda1"];
6362           ["vgcreate"; "VG"; "/dev/sda1"];
6363           ["lvcreate"; "LV"; "VG"; "8"];
6364           ["mkfs"; "ext2"; "/dev/VG/LV"];
6365           ["mount"; "/dev/VG/LV"; "/"]]
6366    | InitISOFS ->
6367        pr "  /* InitISOFS for %s */\n" test_name;
6368        List.iter (generate_test_command_call test_name)
6369          [["blockdev_setrw"; "/dev/sda"];
6370           ["umount_all"];
6371           ["lvm_remove_all"];
6372           ["mount_ro"; "/dev/sdd"; "/"]]
6373   );
6374
6375   let get_seq_last = function
6376     | [] ->
6377         failwithf "%s: you cannot use [] (empty list) when expecting a command"
6378           test_name
6379     | seq ->
6380         let seq = List.rev seq in
6381         List.rev (List.tl seq), List.hd seq
6382   in
6383
6384   match test with
6385   | TestRun seq ->
6386       pr "  /* TestRun for %s (%d) */\n" name i;
6387       List.iter (generate_test_command_call test_name) seq
6388   | TestOutput (seq, expected) ->
6389       pr "  /* TestOutput for %s (%d) */\n" name i;
6390       pr "  const char *expected = \"%s\";\n" (c_quote expected);
6391       let seq, last = get_seq_last seq in
6392       let test () =
6393         pr "    if (STRNEQ (r, expected)) {\n";
6394         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6395         pr "      return -1;\n";
6396         pr "    }\n"
6397       in
6398       List.iter (generate_test_command_call test_name) seq;
6399       generate_test_command_call ~test test_name last
6400   | TestOutputList (seq, expected) ->
6401       pr "  /* TestOutputList for %s (%d) */\n" name i;
6402       let seq, last = get_seq_last seq in
6403       let test () =
6404         iteri (
6405           fun i str ->
6406             pr "    if (!r[%d]) {\n" i;
6407             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6408             pr "      print_strings (r);\n";
6409             pr "      return -1;\n";
6410             pr "    }\n";
6411             pr "    {\n";
6412             pr "      const char *expected = \"%s\";\n" (c_quote str);
6413             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
6414             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6415             pr "        return -1;\n";
6416             pr "      }\n";
6417             pr "    }\n"
6418         ) expected;
6419         pr "    if (r[%d] != NULL) {\n" (List.length expected);
6420         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6421           test_name;
6422         pr "      print_strings (r);\n";
6423         pr "      return -1;\n";
6424         pr "    }\n"
6425       in
6426       List.iter (generate_test_command_call test_name) seq;
6427       generate_test_command_call ~test test_name last
6428   | TestOutputListOfDevices (seq, expected) ->
6429       pr "  /* TestOutputListOfDevices for %s (%d) */\n" name i;
6430       let seq, last = get_seq_last seq in
6431       let test () =
6432         iteri (
6433           fun i str ->
6434             pr "    if (!r[%d]) {\n" i;
6435             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6436             pr "      print_strings (r);\n";
6437             pr "      return -1;\n";
6438             pr "    }\n";
6439             pr "    {\n";
6440             pr "      const char *expected = \"%s\";\n" (c_quote str);
6441             pr "      r[%d][5] = 's';\n" i;
6442             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
6443             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6444             pr "        return -1;\n";
6445             pr "      }\n";
6446             pr "    }\n"
6447         ) expected;
6448         pr "    if (r[%d] != NULL) {\n" (List.length expected);
6449         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6450           test_name;
6451         pr "      print_strings (r);\n";
6452         pr "      return -1;\n";
6453         pr "    }\n"
6454       in
6455       List.iter (generate_test_command_call test_name) seq;
6456       generate_test_command_call ~test test_name last
6457   | TestOutputInt (seq, expected) ->
6458       pr "  /* TestOutputInt for %s (%d) */\n" name i;
6459       let seq, last = get_seq_last seq in
6460       let test () =
6461         pr "    if (r != %d) {\n" expected;
6462         pr "      fprintf (stderr, \"%s: expected %d but got %%d\\n\","
6463           test_name expected;
6464         pr "               (int) r);\n";
6465         pr "      return -1;\n";
6466         pr "    }\n"
6467       in
6468       List.iter (generate_test_command_call test_name) seq;
6469       generate_test_command_call ~test test_name last
6470   | TestOutputIntOp (seq, op, expected) ->
6471       pr "  /* TestOutputIntOp for %s (%d) */\n" name i;
6472       let seq, last = get_seq_last seq in
6473       let test () =
6474         pr "    if (! (r %s %d)) {\n" op expected;
6475         pr "      fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
6476           test_name op expected;
6477         pr "               (int) r);\n";
6478         pr "      return -1;\n";
6479         pr "    }\n"
6480       in
6481       List.iter (generate_test_command_call test_name) seq;
6482       generate_test_command_call ~test test_name last
6483   | TestOutputTrue seq ->
6484       pr "  /* TestOutputTrue for %s (%d) */\n" name i;
6485       let seq, last = get_seq_last seq in
6486       let test () =
6487         pr "    if (!r) {\n";
6488         pr "      fprintf (stderr, \"%s: expected true, got false\\n\");\n"
6489           test_name;
6490         pr "      return -1;\n";
6491         pr "    }\n"
6492       in
6493       List.iter (generate_test_command_call test_name) seq;
6494       generate_test_command_call ~test test_name last
6495   | TestOutputFalse seq ->
6496       pr "  /* TestOutputFalse for %s (%d) */\n" name i;
6497       let seq, last = get_seq_last seq in
6498       let test () =
6499         pr "    if (r) {\n";
6500         pr "      fprintf (stderr, \"%s: expected false, got true\\n\");\n"
6501           test_name;
6502         pr "      return -1;\n";
6503         pr "    }\n"
6504       in
6505       List.iter (generate_test_command_call test_name) seq;
6506       generate_test_command_call ~test test_name last
6507   | TestOutputLength (seq, expected) ->
6508       pr "  /* TestOutputLength for %s (%d) */\n" name i;
6509       let seq, last = get_seq_last seq in
6510       let test () =
6511         pr "    int j;\n";
6512         pr "    for (j = 0; j < %d; ++j)\n" expected;
6513         pr "      if (r[j] == NULL) {\n";
6514         pr "        fprintf (stderr, \"%s: short list returned\\n\");\n"
6515           test_name;
6516         pr "        print_strings (r);\n";
6517         pr "        return -1;\n";
6518         pr "      }\n";
6519         pr "    if (r[j] != NULL) {\n";
6520         pr "      fprintf (stderr, \"%s: long list returned\\n\");\n"
6521           test_name;
6522         pr "      print_strings (r);\n";
6523         pr "      return -1;\n";
6524         pr "    }\n"
6525       in
6526       List.iter (generate_test_command_call test_name) seq;
6527       generate_test_command_call ~test test_name last
6528   | TestOutputBuffer (seq, expected) ->
6529       pr "  /* TestOutputBuffer for %s (%d) */\n" name i;
6530       pr "  const char *expected = \"%s\";\n" (c_quote expected);
6531       let seq, last = get_seq_last seq in
6532       let len = String.length expected in
6533       let test () =
6534         pr "    if (size != %d) {\n" len;
6535         pr "      fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
6536         pr "      return -1;\n";
6537         pr "    }\n";
6538         pr "    if (STRNEQLEN (r, expected, size)) {\n";
6539         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6540         pr "      return -1;\n";
6541         pr "    }\n"
6542       in
6543       List.iter (generate_test_command_call test_name) seq;
6544       generate_test_command_call ~test test_name last
6545   | TestOutputStruct (seq, checks) ->
6546       pr "  /* TestOutputStruct for %s (%d) */\n" name i;
6547       let seq, last = get_seq_last seq in
6548       let test () =
6549         List.iter (
6550           function
6551           | CompareWithInt (field, expected) ->
6552               pr "    if (r->%s != %d) {\n" field expected;
6553               pr "      fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
6554                 test_name field expected;
6555               pr "               (int) r->%s);\n" field;
6556               pr "      return -1;\n";
6557               pr "    }\n"
6558           | CompareWithIntOp (field, op, expected) ->
6559               pr "    if (!(r->%s %s %d)) {\n" field op expected;
6560               pr "      fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
6561                 test_name field op expected;
6562               pr "               (int) r->%s);\n" field;
6563               pr "      return -1;\n";
6564               pr "    }\n"
6565           | CompareWithString (field, expected) ->
6566               pr "    if (STRNEQ (r->%s, \"%s\")) {\n" field expected;
6567               pr "      fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
6568                 test_name field expected;
6569               pr "               r->%s);\n" field;
6570               pr "      return -1;\n";
6571               pr "    }\n"
6572           | CompareFieldsIntEq (field1, field2) ->
6573               pr "    if (r->%s != r->%s) {\n" field1 field2;
6574               pr "      fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
6575                 test_name field1 field2;
6576               pr "               (int) r->%s, (int) r->%s);\n" field1 field2;
6577               pr "      return -1;\n";
6578               pr "    }\n"
6579           | CompareFieldsStrEq (field1, field2) ->
6580               pr "    if (STRNEQ (r->%s, r->%s)) {\n" field1 field2;
6581               pr "      fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
6582                 test_name field1 field2;
6583               pr "               r->%s, r->%s);\n" field1 field2;
6584               pr "      return -1;\n";
6585               pr "    }\n"
6586         ) checks
6587       in
6588       List.iter (generate_test_command_call test_name) seq;
6589       generate_test_command_call ~test test_name last
6590   | TestLastFail seq ->
6591       pr "  /* TestLastFail for %s (%d) */\n" name i;
6592       let seq, last = get_seq_last seq in
6593       List.iter (generate_test_command_call test_name) seq;
6594       generate_test_command_call test_name ~expect_error:true last
6595
6596 (* Generate the code to run a command, leaving the result in 'r'.
6597  * If you expect to get an error then you should set expect_error:true.
6598  *)
6599 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
6600   match cmd with
6601   | [] -> assert false
6602   | name :: args ->
6603       (* Look up the command to find out what args/ret it has. *)
6604       let style =
6605         try
6606           let _, style, _, _, _, _, _ =
6607             List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
6608           style
6609         with Not_found ->
6610           failwithf "%s: in test, command %s was not found" test_name name in
6611
6612       if List.length (snd style) <> List.length args then
6613         failwithf "%s: in test, wrong number of args given to %s"
6614           test_name name;
6615
6616       pr "  {\n";
6617
6618       List.iter (
6619         function
6620         | OptString n, "NULL" -> ()
6621         | Pathname n, arg
6622         | Device n, arg
6623         | Dev_or_Path n, arg
6624         | String n, arg
6625         | OptString n, arg ->
6626             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
6627         | Int _, _
6628         | Int64 _, _
6629         | Bool _, _
6630         | FileIn _, _ | FileOut _, _ -> ()
6631         | StringList n, arg | DeviceList n, arg ->
6632             let strs = string_split " " arg in
6633             iteri (
6634               fun i str ->
6635                 pr "    const char *%s_%d = \"%s\";\n" n i (c_quote str);
6636             ) strs;
6637             pr "    const char *const %s[] = {\n" n;
6638             iteri (
6639               fun i _ -> pr "      %s_%d,\n" n i
6640             ) strs;
6641             pr "      NULL\n";
6642             pr "    };\n";
6643       ) (List.combine (snd style) args);
6644
6645       let error_code =
6646         match fst style with
6647         | RErr | RInt _ | RBool _ -> pr "    int r;\n"; "-1"
6648         | RInt64 _ -> pr "    int64_t r;\n"; "-1"
6649         | RConstString _ | RConstOptString _ ->
6650             pr "    const char *r;\n"; "NULL"
6651         | RString _ -> pr "    char *r;\n"; "NULL"
6652         | RStringList _ | RHashtable _ ->
6653             pr "    char **r;\n";
6654             pr "    int i;\n";
6655             "NULL"
6656         | RStruct (_, typ) ->
6657             pr "    struct guestfs_%s *r;\n" typ; "NULL"
6658         | RStructList (_, typ) ->
6659             pr "    struct guestfs_%s_list *r;\n" typ; "NULL"
6660         | RBufferOut _ ->
6661             pr "    char *r;\n";
6662             pr "    size_t size;\n";
6663             "NULL" in
6664
6665       pr "    suppress_error = %d;\n" (if expect_error then 1 else 0);
6666       pr "    r = guestfs_%s (g" name;
6667
6668       (* Generate the parameters. *)
6669       List.iter (
6670         function
6671         | OptString _, "NULL" -> pr ", NULL"
6672         | Pathname n, _
6673         | Device n, _ | Dev_or_Path n, _
6674         | String n, _
6675         | OptString n, _ ->
6676             pr ", %s" n
6677         | FileIn _, arg | FileOut _, arg ->
6678             pr ", \"%s\"" (c_quote arg)
6679         | StringList n, _ | DeviceList n, _ ->
6680             pr ", (char **) %s" n
6681         | Int _, arg ->
6682             let i =
6683               try int_of_string arg
6684               with Failure "int_of_string" ->
6685                 failwithf "%s: expecting an int, but got '%s'" test_name arg in
6686             pr ", %d" i
6687         | Int64 _, arg ->
6688             let i =
6689               try Int64.of_string arg
6690               with Failure "int_of_string" ->
6691                 failwithf "%s: expecting an int64, but got '%s'" test_name arg in
6692             pr ", %Ld" i
6693         | Bool _, arg ->
6694             let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
6695       ) (List.combine (snd style) args);
6696
6697       (match fst style with
6698        | RBufferOut _ -> pr ", &size"
6699        | _ -> ()
6700       );
6701
6702       pr ");\n";
6703
6704       if not expect_error then
6705         pr "    if (r == %s)\n" error_code
6706       else
6707         pr "    if (r != %s)\n" error_code;
6708       pr "      return -1;\n";
6709
6710       (* Insert the test code. *)
6711       (match test with
6712        | None -> ()
6713        | Some f -> f ()
6714       );
6715
6716       (match fst style with
6717        | RErr | RInt _ | RInt64 _ | RBool _
6718        | RConstString _ | RConstOptString _ -> ()
6719        | RString _ | RBufferOut _ -> pr "    free (r);\n"
6720        | RStringList _ | RHashtable _ ->
6721            pr "    for (i = 0; r[i] != NULL; ++i)\n";
6722            pr "      free (r[i]);\n";
6723            pr "    free (r);\n"
6724        | RStruct (_, typ) ->
6725            pr "    guestfs_free_%s (r);\n" typ
6726        | RStructList (_, typ) ->
6727            pr "    guestfs_free_%s_list (r);\n" typ
6728       );
6729
6730       pr "  }\n"
6731
6732 and c_quote str =
6733   let str = replace_str str "\r" "\\r" in
6734   let str = replace_str str "\n" "\\n" in
6735   let str = replace_str str "\t" "\\t" in
6736   let str = replace_str str "\000" "\\0" in
6737   str
6738
6739 (* Generate a lot of different functions for guestfish. *)
6740 and generate_fish_cmds () =
6741   generate_header CStyle GPLv2;
6742
6743   let all_functions =
6744     List.filter (
6745       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
6746     ) all_functions in
6747   let all_functions_sorted =
6748     List.filter (
6749       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
6750     ) all_functions_sorted in
6751
6752   pr "#include <stdio.h>\n";
6753   pr "#include <stdlib.h>\n";
6754   pr "#include <string.h>\n";
6755   pr "#include <inttypes.h>\n";
6756   pr "\n";
6757   pr "#include <guestfs.h>\n";
6758   pr "#include \"c-ctype.h\"\n";
6759   pr "#include \"fish.h\"\n";
6760   pr "\n";
6761
6762   (* list_commands function, which implements guestfish -h *)
6763   pr "void list_commands (void)\n";
6764   pr "{\n";
6765   pr "  printf (\"    %%-16s     %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
6766   pr "  list_builtin_commands ();\n";
6767   List.iter (
6768     fun (name, _, _, flags, _, shortdesc, _) ->
6769       let name = replace_char name '_' '-' in
6770       pr "  printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
6771         name shortdesc
6772   ) all_functions_sorted;
6773   pr "  printf (\"    %%s\\n\",";
6774   pr "          _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
6775   pr "}\n";
6776   pr "\n";
6777
6778   (* display_command function, which implements guestfish -h cmd *)
6779   pr "void display_command (const char *cmd)\n";
6780   pr "{\n";
6781   List.iter (
6782     fun (name, style, _, flags, _, shortdesc, longdesc) ->
6783       let name2 = replace_char name '_' '-' in
6784       let alias =
6785         try find_map (function FishAlias n -> Some n | _ -> None) flags
6786         with Not_found -> name in
6787       let longdesc = replace_str longdesc "C<guestfs_" "C<" in
6788       let synopsis =
6789         match snd style with
6790         | [] -> name2
6791         | args ->
6792             sprintf "%s %s"
6793               name2 (String.concat " " (List.map name_of_argt args)) in
6794
6795       let warnings =
6796         if List.mem ProtocolLimitWarning flags then
6797           ("\n\n" ^ protocol_limit_warning)
6798         else "" in
6799
6800       (* For DangerWillRobinson commands, we should probably have
6801        * guestfish prompt before allowing you to use them (especially
6802        * in interactive mode). XXX
6803        *)
6804       let warnings =
6805         warnings ^
6806           if List.mem DangerWillRobinson flags then
6807             ("\n\n" ^ danger_will_robinson)
6808           else "" in
6809
6810       let warnings =
6811         warnings ^
6812           match deprecation_notice flags with
6813           | None -> ""
6814           | Some txt -> "\n\n" ^ txt in
6815
6816       let describe_alias =
6817         if name <> alias then
6818           sprintf "\n\nYou can use '%s' as an alias for this command." alias
6819         else "" in
6820
6821       pr "  if (";
6822       pr "STRCASEEQ (cmd, \"%s\")" name;
6823       if name <> name2 then
6824         pr " || STRCASEEQ (cmd, \"%s\")" name2;
6825       if name <> alias then
6826         pr " || STRCASEEQ (cmd, \"%s\")" alias;
6827       pr ")\n";
6828       pr "    pod2text (\"%s\", _(\"%s\"), %S);\n"
6829         name2 shortdesc
6830         ("=head1 SYNOPSIS\n\n " ^ synopsis ^ "\n\n" ^
6831          "=head1 DESCRIPTION\n\n" ^
6832          longdesc ^ warnings ^ describe_alias);
6833       pr "  else\n"
6834   ) all_functions;
6835   pr "    display_builtin_command (cmd);\n";
6836   pr "}\n";
6837   pr "\n";
6838
6839   let emit_print_list_function typ =
6840     pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
6841       typ typ typ;
6842     pr "{\n";
6843     pr "  unsigned int i;\n";
6844     pr "\n";
6845     pr "  for (i = 0; i < %ss->len; ++i) {\n" typ;
6846     pr "    printf (\"[%%d] = {\\n\", i);\n";
6847     pr "    print_%s_indent (&%ss->val[i], \"  \");\n" typ typ;
6848     pr "    printf (\"}\\n\");\n";
6849     pr "  }\n";
6850     pr "}\n";
6851     pr "\n";
6852   in
6853
6854   (* print_* functions *)
6855   List.iter (
6856     fun (typ, cols) ->
6857       let needs_i =
6858         List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
6859
6860       pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
6861       pr "{\n";
6862       if needs_i then (
6863         pr "  unsigned int i;\n";
6864         pr "\n"
6865       );
6866       List.iter (
6867         function
6868         | name, FString ->
6869             pr "  printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
6870         | name, FUUID ->
6871             pr "  printf (\"%%s%s: \", indent);\n" name;
6872             pr "  for (i = 0; i < 32; ++i)\n";
6873             pr "    printf (\"%%c\", %s->%s[i]);\n" typ name;
6874             pr "  printf (\"\\n\");\n"
6875         | name, FBuffer ->
6876             pr "  printf (\"%%s%s: \", indent);\n" name;
6877             pr "  for (i = 0; i < %s->%s_len; ++i)\n" typ name;
6878             pr "    if (c_isprint (%s->%s[i]))\n" typ name;
6879             pr "      printf (\"%%c\", %s->%s[i]);\n" typ name;
6880             pr "    else\n";
6881             pr "      printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
6882             pr "  printf (\"\\n\");\n"
6883         | name, (FUInt64|FBytes) ->
6884             pr "  printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
6885               name typ name
6886         | name, FInt64 ->
6887             pr "  printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
6888               name typ name
6889         | name, FUInt32 ->
6890             pr "  printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
6891               name typ name
6892         | name, FInt32 ->
6893             pr "  printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
6894               name typ name
6895         | name, FChar ->
6896             pr "  printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
6897               name typ name
6898         | name, FOptPercent ->
6899             pr "  if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
6900               typ name name typ name;
6901             pr "  else printf (\"%%s%s: \\n\", indent);\n" name
6902       ) cols;
6903       pr "}\n";
6904       pr "\n";
6905   ) structs;
6906
6907   (* Emit a print_TYPE_list function definition only if that function is used. *)
6908   List.iter (
6909     function
6910     | typ, (RStructListOnly | RStructAndList) ->
6911         (* generate the function for typ *)
6912         emit_print_list_function typ
6913     | typ, _ -> () (* empty *)
6914   ) (rstructs_used_by all_functions);
6915
6916   (* Emit a print_TYPE function definition only if that function is used. *)
6917   List.iter (
6918     function
6919     | typ, (RStructOnly | RStructAndList) ->
6920         pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
6921         pr "{\n";
6922         pr "  print_%s_indent (%s, \"\");\n" typ typ;
6923         pr "}\n";
6924         pr "\n";
6925     | typ, _ -> () (* empty *)
6926   ) (rstructs_used_by all_functions);
6927
6928   (* run_<action> actions *)
6929   List.iter (
6930     fun (name, style, _, flags, _, _, _) ->
6931       pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
6932       pr "{\n";
6933       (match fst style with
6934        | RErr
6935        | RInt _
6936        | RBool _ -> pr "  int r;\n"
6937        | RInt64 _ -> pr "  int64_t r;\n"
6938        | RConstString _ | RConstOptString _ -> pr "  const char *r;\n"
6939        | RString _ -> pr "  char *r;\n"
6940        | RStringList _ | RHashtable _ -> pr "  char **r;\n"
6941        | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ
6942        | RStructList (_, typ) -> pr "  struct guestfs_%s_list *r;\n" typ
6943        | RBufferOut _ ->
6944            pr "  char *r;\n";
6945            pr "  size_t size;\n";
6946       );
6947       List.iter (
6948         function
6949         | Device n
6950         | String n
6951         | OptString n
6952         | FileIn n
6953         | FileOut n -> pr "  const char *%s;\n" n
6954         | Pathname n
6955         | Dev_or_Path n -> pr "  char *%s;\n" n
6956         | StringList n | DeviceList n -> pr "  char **%s;\n" n
6957         | Bool n -> pr "  int %s;\n" n
6958         | Int n -> pr "  int %s;\n" n
6959         | Int64 n -> pr "  int64_t %s;\n" n
6960       ) (snd style);
6961
6962       (* Check and convert parameters. *)
6963       let argc_expected = List.length (snd style) in
6964       pr "  if (argc != %d) {\n" argc_expected;
6965       pr "    fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
6966         argc_expected;
6967       pr "    fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
6968       pr "    return -1;\n";
6969       pr "  }\n";
6970       iteri (
6971         fun i ->
6972           function
6973           | Device name
6974           | String name ->
6975               pr "  %s = argv[%d];\n" name i
6976           | Pathname name
6977           | Dev_or_Path name ->
6978               pr "  %s = resolve_win_path (argv[%d]);\n" name i;
6979               pr "  if (%s == NULL) return -1;\n" name
6980           | OptString name ->
6981               pr "  %s = STRNEQ (argv[%d], \"\") ? argv[%d] : NULL;\n"
6982                 name i i
6983           | FileIn name ->
6984               pr "  %s = STRNEQ (argv[%d], \"-\") ? argv[%d] : \"/dev/stdin\";\n"
6985                 name i i
6986           | FileOut name ->
6987               pr "  %s = STRNEQ (argv[%d], \"-\") ? argv[%d] : \"/dev/stdout\";\n"
6988                 name i i
6989           | StringList name | DeviceList name ->
6990               pr "  %s = parse_string_list (argv[%d]);\n" name i;
6991               pr "  if (%s == NULL) return -1;\n" name;
6992           | Bool name ->
6993               pr "  %s = is_true (argv[%d]) ? 1 : 0;\n" name i
6994           | Int name ->
6995               pr "  %s = atoi (argv[%d]);\n" name i
6996           | Int64 name ->
6997               pr "  %s = atoll (argv[%d]);\n" name i
6998       ) (snd style);
6999
7000       (* Call C API function. *)
7001       let fn =
7002         try find_map (function FishAction n -> Some n | _ -> None) flags
7003         with Not_found -> sprintf "guestfs_%s" name in
7004       pr "  r = %s " fn;
7005       generate_c_call_args ~handle:"g" style;
7006       pr ";\n";
7007
7008       List.iter (
7009         function
7010         | Device name | String name
7011         | OptString name | FileIn name | FileOut name | Bool name
7012         | Int name | Int64 name -> ()
7013         | Pathname name | Dev_or_Path name ->
7014             pr "  free (%s);\n" name
7015         | StringList name | DeviceList name ->
7016             pr "  free_strings (%s);\n" name
7017       ) (snd style);
7018
7019       (* Check return value for errors and display command results. *)
7020       (match fst style with
7021        | RErr -> pr "  return r;\n"
7022        | RInt _ ->
7023            pr "  if (r == -1) return -1;\n";
7024            pr "  printf (\"%%d\\n\", r);\n";
7025            pr "  return 0;\n"
7026        | RInt64 _ ->
7027            pr "  if (r == -1) return -1;\n";
7028            pr "  printf (\"%%\" PRIi64 \"\\n\", r);\n";
7029            pr "  return 0;\n"
7030        | RBool _ ->
7031            pr "  if (r == -1) return -1;\n";
7032            pr "  if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
7033            pr "  return 0;\n"
7034        | RConstString _ ->
7035            pr "  if (r == NULL) return -1;\n";
7036            pr "  printf (\"%%s\\n\", r);\n";
7037            pr "  return 0;\n"
7038        | RConstOptString _ ->
7039            pr "  printf (\"%%s\\n\", r ? : \"(null)\");\n";
7040            pr "  return 0;\n"
7041        | RString _ ->
7042            pr "  if (r == NULL) return -1;\n";
7043            pr "  printf (\"%%s\\n\", r);\n";
7044            pr "  free (r);\n";
7045            pr "  return 0;\n"
7046        | RStringList _ ->
7047            pr "  if (r == NULL) return -1;\n";
7048            pr "  print_strings (r);\n";
7049            pr "  free_strings (r);\n";
7050            pr "  return 0;\n"
7051        | RStruct (_, typ) ->
7052            pr "  if (r == NULL) return -1;\n";
7053            pr "  print_%s (r);\n" typ;
7054            pr "  guestfs_free_%s (r);\n" typ;
7055            pr "  return 0;\n"
7056        | RStructList (_, typ) ->
7057            pr "  if (r == NULL) return -1;\n";
7058            pr "  print_%s_list (r);\n" typ;
7059            pr "  guestfs_free_%s_list (r);\n" typ;
7060            pr "  return 0;\n"
7061        | RHashtable _ ->
7062            pr "  if (r == NULL) return -1;\n";
7063            pr "  print_table (r);\n";
7064            pr "  free_strings (r);\n";
7065            pr "  return 0;\n"
7066        | RBufferOut _ ->
7067            pr "  if (r == NULL) return -1;\n";
7068            pr "  fwrite (r, size, 1, stdout);\n";
7069            pr "  free (r);\n";
7070            pr "  return 0;\n"
7071       );
7072       pr "}\n";
7073       pr "\n"
7074   ) all_functions;
7075
7076   (* run_action function *)
7077   pr "int run_action (const char *cmd, int argc, char *argv[])\n";
7078   pr "{\n";
7079   List.iter (
7080     fun (name, _, _, flags, _, _, _) ->
7081       let name2 = replace_char name '_' '-' in
7082       let alias =
7083         try find_map (function FishAlias n -> Some n | _ -> None) flags
7084         with Not_found -> name in
7085       pr "  if (";
7086       pr "STRCASEEQ (cmd, \"%s\")" name;
7087       if name <> name2 then
7088         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7089       if name <> alias then
7090         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7091       pr ")\n";
7092       pr "    return run_%s (cmd, argc, argv);\n" name;
7093       pr "  else\n";
7094   ) all_functions;
7095   pr "    {\n";
7096   pr "      fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
7097   pr "      return -1;\n";
7098   pr "    }\n";
7099   pr "  return 0;\n";
7100   pr "}\n";
7101   pr "\n"
7102
7103 (* Readline completion for guestfish. *)
7104 and generate_fish_completion () =
7105   generate_header CStyle GPLv2;
7106
7107   let all_functions =
7108     List.filter (
7109       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7110     ) all_functions in
7111
7112   pr "\
7113 #include <config.h>
7114
7115 #include <stdio.h>
7116 #include <stdlib.h>
7117 #include <string.h>
7118
7119 #ifdef HAVE_LIBREADLINE
7120 #include <readline/readline.h>
7121 #endif
7122
7123 #include \"fish.h\"
7124
7125 #ifdef HAVE_LIBREADLINE
7126
7127 static const char *const commands[] = {
7128   BUILTIN_COMMANDS_FOR_COMPLETION,
7129 ";
7130
7131   (* Get the commands, including the aliases.  They don't need to be
7132    * sorted - the generator() function just does a dumb linear search.
7133    *)
7134   let commands =
7135     List.map (
7136       fun (name, _, _, flags, _, _, _) ->
7137         let name2 = replace_char name '_' '-' in
7138         let alias =
7139           try find_map (function FishAlias n -> Some n | _ -> None) flags
7140           with Not_found -> name in
7141
7142         if name <> alias then [name2; alias] else [name2]
7143     ) all_functions in
7144   let commands = List.flatten commands in
7145
7146   List.iter (pr "  \"%s\",\n") commands;
7147
7148   pr "  NULL
7149 };
7150
7151 static char *
7152 generator (const char *text, int state)
7153 {
7154   static int index, len;
7155   const char *name;
7156
7157   if (!state) {
7158     index = 0;
7159     len = strlen (text);
7160   }
7161
7162   rl_attempted_completion_over = 1;
7163
7164   while ((name = commands[index]) != NULL) {
7165     index++;
7166     if (STRCASEEQLEN (name, text, len))
7167       return strdup (name);
7168   }
7169
7170   return NULL;
7171 }
7172
7173 #endif /* HAVE_LIBREADLINE */
7174
7175 char **do_completion (const char *text, int start, int end)
7176 {
7177   char **matches = NULL;
7178
7179 #ifdef HAVE_LIBREADLINE
7180   rl_completion_append_character = ' ';
7181
7182   if (start == 0)
7183     matches = rl_completion_matches (text, generator);
7184   else if (complete_dest_paths)
7185     matches = rl_completion_matches (text, complete_dest_paths_generator);
7186 #endif
7187
7188   return matches;
7189 }
7190 ";
7191
7192 (* Generate the POD documentation for guestfish. *)
7193 and generate_fish_actions_pod () =
7194   let all_functions_sorted =
7195     List.filter (
7196       fun (_, _, _, flags, _, _, _) ->
7197         not (List.mem NotInFish flags || List.mem NotInDocs flags)
7198     ) all_functions_sorted in
7199
7200   let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
7201
7202   List.iter (
7203     fun (name, style, _, flags, _, _, longdesc) ->
7204       let longdesc =
7205         Str.global_substitute rex (
7206           fun s ->
7207             let sub =
7208               try Str.matched_group 1 s
7209               with Not_found ->
7210                 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
7211             "C<" ^ replace_char sub '_' '-' ^ ">"
7212         ) longdesc in
7213       let name = replace_char name '_' '-' in
7214       let alias =
7215         try find_map (function FishAlias n -> Some n | _ -> None) flags
7216         with Not_found -> name in
7217
7218       pr "=head2 %s" name;
7219       if name <> alias then
7220         pr " | %s" alias;
7221       pr "\n";
7222       pr "\n";
7223       pr " %s" name;
7224       List.iter (
7225         function
7226         | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
7227         | OptString n -> pr " %s" n
7228         | StringList n | DeviceList n -> pr " '%s ...'" n
7229         | Bool _ -> pr " true|false"
7230         | Int n -> pr " %s" n
7231         | Int64 n -> pr " %s" n
7232         | FileIn n | FileOut n -> pr " (%s|-)" n
7233       ) (snd style);
7234       pr "\n";
7235       pr "\n";
7236       pr "%s\n\n" longdesc;
7237
7238       if List.exists (function FileIn _ | FileOut _ -> true
7239                       | _ -> false) (snd style) then
7240         pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
7241
7242       if List.mem ProtocolLimitWarning flags then
7243         pr "%s\n\n" protocol_limit_warning;
7244
7245       if List.mem DangerWillRobinson flags then
7246         pr "%s\n\n" danger_will_robinson;
7247
7248       match deprecation_notice flags with
7249       | None -> ()
7250       | Some txt -> pr "%s\n\n" txt
7251   ) all_functions_sorted
7252
7253 (* Generate a C function prototype. *)
7254 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
7255     ?(single_line = false) ?(newline = false) ?(in_daemon = false)
7256     ?(prefix = "")
7257     ?handle name style =
7258   if extern then pr "extern ";
7259   if static then pr "static ";
7260   (match fst style with
7261    | RErr -> pr "int "
7262    | RInt _ -> pr "int "
7263    | RInt64 _ -> pr "int64_t "
7264    | RBool _ -> pr "int "
7265    | RConstString _ | RConstOptString _ -> pr "const char *"
7266    | RString _ | RBufferOut _ -> pr "char *"
7267    | RStringList _ | RHashtable _ -> pr "char **"
7268    | RStruct (_, typ) ->
7269        if not in_daemon then pr "struct guestfs_%s *" typ
7270        else pr "guestfs_int_%s *" typ
7271    | RStructList (_, typ) ->
7272        if not in_daemon then pr "struct guestfs_%s_list *" typ
7273        else pr "guestfs_int_%s_list *" typ
7274   );
7275   let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
7276   pr "%s%s (" prefix name;
7277   if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
7278     pr "void"
7279   else (
7280     let comma = ref false in
7281     (match handle with
7282      | None -> ()
7283      | Some handle -> pr "guestfs_h *%s" handle; comma := true
7284     );
7285     let next () =
7286       if !comma then (
7287         if single_line then pr ", " else pr ",\n\t\t"
7288       );
7289       comma := true
7290     in
7291     List.iter (
7292       function
7293       | Pathname n
7294       | Device n | Dev_or_Path n
7295       | String n
7296       | OptString n ->
7297           next ();
7298           pr "const char *%s" n
7299       | StringList n | DeviceList n ->
7300           next ();
7301           pr "char *const *%s" n
7302       | Bool n -> next (); pr "int %s" n
7303       | Int n -> next (); pr "int %s" n
7304       | Int64 n -> next (); pr "int64_t %s" n
7305       | FileIn n
7306       | FileOut n ->
7307           if not in_daemon then (next (); pr "const char *%s" n)
7308     ) (snd style);
7309     if is_RBufferOut then (next (); pr "size_t *size_r");
7310   );
7311   pr ")";
7312   if semicolon then pr ";";
7313   if newline then pr "\n"
7314
7315 (* Generate C call arguments, eg "(handle, foo, bar)" *)
7316 and generate_c_call_args ?handle ?(decl = false) style =
7317   pr "(";
7318   let comma = ref false in
7319   let next () =
7320     if !comma then pr ", ";
7321     comma := true
7322   in
7323   (match handle with
7324    | None -> ()
7325    | Some handle -> pr "%s" handle; comma := true
7326   );
7327   List.iter (
7328     fun arg ->
7329       next ();
7330       pr "%s" (name_of_argt arg)
7331   ) (snd style);
7332   (* For RBufferOut calls, add implicit &size parameter. *)
7333   if not decl then (
7334     match fst style with
7335     | RBufferOut _ ->
7336         next ();
7337         pr "&size"
7338     | _ -> ()
7339   );
7340   pr ")"
7341
7342 (* Generate the OCaml bindings interface. *)
7343 and generate_ocaml_mli () =
7344   generate_header OCamlStyle LGPLv2;
7345
7346   pr "\
7347 (** For API documentation you should refer to the C API
7348     in the guestfs(3) manual page.  The OCaml API uses almost
7349     exactly the same calls. *)
7350
7351 type t
7352 (** A [guestfs_h] handle. *)
7353
7354 exception Error of string
7355 (** This exception is raised when there is an error. *)
7356
7357 exception Handle_closed of string
7358 (** This exception is raised if you use a {!Guestfs.t} handle
7359     after calling {!close} on it.  The string is the name of
7360     the function. *)
7361
7362 val create : unit -> t
7363 (** Create a {!Guestfs.t} handle. *)
7364
7365 val close : t -> unit
7366 (** Close the {!Guestfs.t} handle and free up all resources used
7367     by it immediately.
7368
7369     Handles are closed by the garbage collector when they become
7370     unreferenced, but callers can call this in order to provide
7371     predictable cleanup. *)
7372
7373 ";
7374   generate_ocaml_structure_decls ();
7375
7376   (* The actions. *)
7377   List.iter (
7378     fun (name, style, _, _, _, shortdesc, _) ->
7379       generate_ocaml_prototype name style;
7380       pr "(** %s *)\n" shortdesc;
7381       pr "\n"
7382   ) all_functions_sorted
7383
7384 (* Generate the OCaml bindings implementation. *)
7385 and generate_ocaml_ml () =
7386   generate_header OCamlStyle LGPLv2;
7387
7388   pr "\
7389 type t
7390
7391 exception Error of string
7392 exception Handle_closed of string
7393
7394 external create : unit -> t = \"ocaml_guestfs_create\"
7395 external close : t -> unit = \"ocaml_guestfs_close\"
7396
7397 (* Give the exceptions names, so they can be raised from the C code. *)
7398 let () =
7399   Callback.register_exception \"ocaml_guestfs_error\" (Error \"\");
7400   Callback.register_exception \"ocaml_guestfs_closed\" (Handle_closed \"\")
7401
7402 ";
7403
7404   generate_ocaml_structure_decls ();
7405
7406   (* The actions. *)
7407   List.iter (
7408     fun (name, style, _, _, _, shortdesc, _) ->
7409       generate_ocaml_prototype ~is_external:true name style;
7410   ) all_functions_sorted
7411
7412 (* Generate the OCaml bindings C implementation. *)
7413 and generate_ocaml_c () =
7414   generate_header CStyle LGPLv2;
7415
7416   pr "\
7417 #include <stdio.h>
7418 #include <stdlib.h>
7419 #include <string.h>
7420
7421 #include <caml/config.h>
7422 #include <caml/alloc.h>
7423 #include <caml/callback.h>
7424 #include <caml/fail.h>
7425 #include <caml/memory.h>
7426 #include <caml/mlvalues.h>
7427 #include <caml/signals.h>
7428
7429 #include <guestfs.h>
7430
7431 #include \"guestfs_c.h\"
7432
7433 /* Copy a hashtable of string pairs into an assoc-list.  We return
7434  * the list in reverse order, but hashtables aren't supposed to be
7435  * ordered anyway.
7436  */
7437 static CAMLprim value
7438 copy_table (char * const * argv)
7439 {
7440   CAMLparam0 ();
7441   CAMLlocal5 (rv, pairv, kv, vv, cons);
7442   int i;
7443
7444   rv = Val_int (0);
7445   for (i = 0; argv[i] != NULL; i += 2) {
7446     kv = caml_copy_string (argv[i]);
7447     vv = caml_copy_string (argv[i+1]);
7448     pairv = caml_alloc (2, 0);
7449     Store_field (pairv, 0, kv);
7450     Store_field (pairv, 1, vv);
7451     cons = caml_alloc (2, 0);
7452     Store_field (cons, 1, rv);
7453     rv = cons;
7454     Store_field (cons, 0, pairv);
7455   }
7456
7457   CAMLreturn (rv);
7458 }
7459
7460 ";
7461
7462   (* Struct copy functions. *)
7463
7464   let emit_ocaml_copy_list_function typ =
7465     pr "static CAMLprim value\n";
7466     pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
7467     pr "{\n";
7468     pr "  CAMLparam0 ();\n";
7469     pr "  CAMLlocal2 (rv, v);\n";
7470     pr "  unsigned int i;\n";
7471     pr "\n";
7472     pr "  if (%ss->len == 0)\n" typ;
7473     pr "    CAMLreturn (Atom (0));\n";
7474     pr "  else {\n";
7475     pr "    rv = caml_alloc (%ss->len, 0);\n" typ;
7476     pr "    for (i = 0; i < %ss->len; ++i) {\n" typ;
7477     pr "      v = copy_%s (&%ss->val[i]);\n" typ typ;
7478     pr "      caml_modify (&Field (rv, i), v);\n";
7479     pr "    }\n";
7480     pr "    CAMLreturn (rv);\n";
7481     pr "  }\n";
7482     pr "}\n";
7483     pr "\n";
7484   in
7485
7486   List.iter (
7487     fun (typ, cols) ->
7488       let has_optpercent_col =
7489         List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
7490
7491       pr "static CAMLprim value\n";
7492       pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
7493       pr "{\n";
7494       pr "  CAMLparam0 ();\n";
7495       if has_optpercent_col then
7496         pr "  CAMLlocal3 (rv, v, v2);\n"
7497       else
7498         pr "  CAMLlocal2 (rv, v);\n";
7499       pr "\n";
7500       pr "  rv = caml_alloc (%d, 0);\n" (List.length cols);
7501       iteri (
7502         fun i col ->
7503           (match col with
7504            | name, FString ->
7505                pr "  v = caml_copy_string (%s->%s);\n" typ name
7506            | name, FBuffer ->
7507                pr "  v = caml_alloc_string (%s->%s_len);\n" typ name;
7508                pr "  memcpy (String_val (v), %s->%s, %s->%s_len);\n"
7509                  typ name typ name
7510            | name, FUUID ->
7511                pr "  v = caml_alloc_string (32);\n";
7512                pr "  memcpy (String_val (v), %s->%s, 32);\n" typ name
7513            | name, (FBytes|FInt64|FUInt64) ->
7514                pr "  v = caml_copy_int64 (%s->%s);\n" typ name
7515            | name, (FInt32|FUInt32) ->
7516                pr "  v = caml_copy_int32 (%s->%s);\n" typ name
7517            | name, FOptPercent ->
7518                pr "  if (%s->%s >= 0) { /* Some %s */\n" typ name name;
7519                pr "    v2 = caml_copy_double (%s->%s);\n" typ name;
7520                pr "    v = caml_alloc (1, 0);\n";
7521                pr "    Store_field (v, 0, v2);\n";
7522                pr "  } else /* None */\n";
7523                pr "    v = Val_int (0);\n";
7524            | name, FChar ->
7525                pr "  v = Val_int (%s->%s);\n" typ name
7526           );
7527           pr "  Store_field (rv, %d, v);\n" i
7528       ) cols;
7529       pr "  CAMLreturn (rv);\n";
7530       pr "}\n";
7531       pr "\n";
7532   ) structs;
7533
7534   (* Emit a copy_TYPE_list function definition only if that function is used. *)
7535   List.iter (
7536     function
7537     | typ, (RStructListOnly | RStructAndList) ->
7538         (* generate the function for typ *)
7539         emit_ocaml_copy_list_function typ
7540     | typ, _ -> () (* empty *)
7541   ) (rstructs_used_by all_functions);
7542
7543   (* The wrappers. *)
7544   List.iter (
7545     fun (name, style, _, _, _, _, _) ->
7546       pr "/* Automatically generated wrapper for function\n";
7547       pr " * ";
7548       generate_ocaml_prototype name style;
7549       pr " */\n";
7550       pr "\n";
7551
7552       let params =
7553         "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
7554
7555       let needs_extra_vs =
7556         match fst style with RConstOptString _ -> true | _ -> false in
7557
7558       pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
7559       pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
7560       List.iter (pr ", value %s") (List.tl params); pr ");\n";
7561       pr "\n";
7562
7563       pr "CAMLprim value\n";
7564       pr "ocaml_guestfs_%s (value %s" name (List.hd params);
7565       List.iter (pr ", value %s") (List.tl params);
7566       pr ")\n";
7567       pr "{\n";
7568
7569       (match params with
7570        | [p1; p2; p3; p4; p5] ->
7571            pr "  CAMLparam5 (%s);\n" (String.concat ", " params)
7572        | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
7573            pr "  CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
7574            pr "  CAMLxparam%d (%s);\n"
7575              (List.length rest) (String.concat ", " rest)
7576        | ps ->
7577            pr "  CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
7578       );
7579       if not needs_extra_vs then
7580         pr "  CAMLlocal1 (rv);\n"
7581       else
7582         pr "  CAMLlocal3 (rv, v, v2);\n";
7583       pr "\n";
7584
7585       pr "  guestfs_h *g = Guestfs_val (gv);\n";
7586       pr "  if (g == NULL)\n";
7587       pr "    ocaml_guestfs_raise_closed (\"%s\");\n" name;
7588       pr "\n";
7589
7590       List.iter (
7591         function
7592         | Pathname n
7593         | Device n | Dev_or_Path n
7594         | String n
7595         | FileIn n
7596         | FileOut n ->
7597             pr "  const char *%s = String_val (%sv);\n" n n
7598         | OptString n ->
7599             pr "  const char *%s =\n" n;
7600             pr "    %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
7601               n n
7602         | StringList n | DeviceList n ->
7603             pr "  char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
7604         | Bool n ->
7605             pr "  int %s = Bool_val (%sv);\n" n n
7606         | Int n ->
7607             pr "  int %s = Int_val (%sv);\n" n n
7608         | Int64 n ->
7609             pr "  int64_t %s = Int64_val (%sv);\n" n n
7610       ) (snd style);
7611       let error_code =
7612         match fst style with
7613         | RErr -> pr "  int r;\n"; "-1"
7614         | RInt _ -> pr "  int r;\n"; "-1"
7615         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
7616         | RBool _ -> pr "  int r;\n"; "-1"
7617         | RConstString _ | RConstOptString _ ->
7618             pr "  const char *r;\n"; "NULL"
7619         | RString _ -> pr "  char *r;\n"; "NULL"
7620         | RStringList _ ->
7621             pr "  int i;\n";
7622             pr "  char **r;\n";
7623             "NULL"
7624         | RStruct (_, typ) ->
7625             pr "  struct guestfs_%s *r;\n" typ; "NULL"
7626         | RStructList (_, typ) ->
7627             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
7628         | RHashtable _ ->
7629             pr "  int i;\n";
7630             pr "  char **r;\n";
7631             "NULL"
7632         | RBufferOut _ ->
7633             pr "  char *r;\n";
7634             pr "  size_t size;\n";
7635             "NULL" in
7636       pr "\n";
7637
7638       pr "  caml_enter_blocking_section ();\n";
7639       pr "  r = guestfs_%s " name;
7640       generate_c_call_args ~handle:"g" style;
7641       pr ";\n";
7642       pr "  caml_leave_blocking_section ();\n";
7643
7644       List.iter (
7645         function
7646         | StringList n | DeviceList n ->
7647             pr "  ocaml_guestfs_free_strings (%s);\n" n;
7648         | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
7649         | Bool _ | Int _ | Int64 _
7650         | FileIn _ | FileOut _ -> ()
7651       ) (snd style);
7652
7653       pr "  if (r == %s)\n" error_code;
7654       pr "    ocaml_guestfs_raise_error (g, \"%s\");\n" name;
7655       pr "\n";
7656
7657       (match fst style with
7658        | RErr -> pr "  rv = Val_unit;\n"
7659        | RInt _ -> pr "  rv = Val_int (r);\n"
7660        | RInt64 _ ->
7661            pr "  rv = caml_copy_int64 (r);\n"
7662        | RBool _ -> pr "  rv = Val_bool (r);\n"
7663        | RConstString _ ->
7664            pr "  rv = caml_copy_string (r);\n"
7665        | RConstOptString _ ->
7666            pr "  if (r) { /* Some string */\n";
7667            pr "    v = caml_alloc (1, 0);\n";
7668            pr "    v2 = caml_copy_string (r);\n";
7669            pr "    Store_field (v, 0, v2);\n";
7670            pr "  } else /* None */\n";
7671            pr "    v = Val_int (0);\n";
7672        | RString _ ->
7673            pr "  rv = caml_copy_string (r);\n";
7674            pr "  free (r);\n"
7675        | RStringList _ ->
7676            pr "  rv = caml_copy_string_array ((const char **) r);\n";
7677            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
7678            pr "  free (r);\n"
7679        | RStruct (_, typ) ->
7680            pr "  rv = copy_%s (r);\n" typ;
7681            pr "  guestfs_free_%s (r);\n" typ;
7682        | RStructList (_, typ) ->
7683            pr "  rv = copy_%s_list (r);\n" typ;
7684            pr "  guestfs_free_%s_list (r);\n" typ;
7685        | RHashtable _ ->
7686            pr "  rv = copy_table (r);\n";
7687            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
7688            pr "  free (r);\n";
7689        | RBufferOut _ ->
7690            pr "  rv = caml_alloc_string (size);\n";
7691            pr "  memcpy (String_val (rv), r, size);\n";
7692       );
7693
7694       pr "  CAMLreturn (rv);\n";
7695       pr "}\n";
7696       pr "\n";
7697
7698       if List.length params > 5 then (
7699         pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
7700         pr "CAMLprim value ";
7701         pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
7702         pr "CAMLprim value\n";
7703         pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
7704         pr "{\n";
7705         pr "  return ocaml_guestfs_%s (argv[0]" name;
7706         iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
7707         pr ");\n";
7708         pr "}\n";
7709         pr "\n"
7710       )
7711   ) all_functions_sorted
7712
7713 and generate_ocaml_structure_decls () =
7714   List.iter (
7715     fun (typ, cols) ->
7716       pr "type %s = {\n" typ;
7717       List.iter (
7718         function
7719         | name, FString -> pr "  %s : string;\n" name
7720         | name, FBuffer -> pr "  %s : string;\n" name
7721         | name, FUUID -> pr "  %s : string;\n" name
7722         | name, (FBytes|FInt64|FUInt64) -> pr "  %s : int64;\n" name
7723         | name, (FInt32|FUInt32) -> pr "  %s : int32;\n" name
7724         | name, FChar -> pr "  %s : char;\n" name
7725         | name, FOptPercent -> pr "  %s : float option;\n" name
7726       ) cols;
7727       pr "}\n";
7728       pr "\n"
7729   ) structs
7730
7731 and generate_ocaml_prototype ?(is_external = false) name style =
7732   if is_external then pr "external " else pr "val ";
7733   pr "%s : t -> " name;
7734   List.iter (
7735     function
7736     | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "string -> "
7737     | OptString _ -> pr "string option -> "
7738     | StringList _ | DeviceList _ -> pr "string array -> "
7739     | Bool _ -> pr "bool -> "
7740     | Int _ -> pr "int -> "
7741     | Int64 _ -> pr "int64 -> "
7742   ) (snd style);
7743   (match fst style with
7744    | RErr -> pr "unit" (* all errors are turned into exceptions *)
7745    | RInt _ -> pr "int"
7746    | RInt64 _ -> pr "int64"
7747    | RBool _ -> pr "bool"
7748    | RConstString _ -> pr "string"
7749    | RConstOptString _ -> pr "string option"
7750    | RString _ | RBufferOut _ -> pr "string"
7751    | RStringList _ -> pr "string array"
7752    | RStruct (_, typ) -> pr "%s" typ
7753    | RStructList (_, typ) -> pr "%s array" typ
7754    | RHashtable _ -> pr "(string * string) list"
7755   );
7756   if is_external then (
7757     pr " = ";
7758     if List.length (snd style) + 1 > 5 then
7759       pr "\"ocaml_guestfs_%s_byte\" " name;
7760     pr "\"ocaml_guestfs_%s\"" name
7761   );
7762   pr "\n"
7763
7764 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
7765 and generate_perl_xs () =
7766   generate_header CStyle LGPLv2;
7767
7768   pr "\
7769 #include \"EXTERN.h\"
7770 #include \"perl.h\"
7771 #include \"XSUB.h\"
7772
7773 #include <guestfs.h>
7774
7775 #ifndef PRId64
7776 #define PRId64 \"lld\"
7777 #endif
7778
7779 static SV *
7780 my_newSVll(long long val) {
7781 #ifdef USE_64_BIT_ALL
7782   return newSViv(val);
7783 #else
7784   char buf[100];
7785   int len;
7786   len = snprintf(buf, 100, \"%%\" PRId64, val);
7787   return newSVpv(buf, len);
7788 #endif
7789 }
7790
7791 #ifndef PRIu64
7792 #define PRIu64 \"llu\"
7793 #endif
7794
7795 static SV *
7796 my_newSVull(unsigned long long val) {
7797 #ifdef USE_64_BIT_ALL
7798   return newSVuv(val);
7799 #else
7800   char buf[100];
7801   int len;
7802   len = snprintf(buf, 100, \"%%\" PRIu64, val);
7803   return newSVpv(buf, len);
7804 #endif
7805 }
7806
7807 /* http://www.perlmonks.org/?node_id=680842 */
7808 static char **
7809 XS_unpack_charPtrPtr (SV *arg) {
7810   char **ret;
7811   AV *av;
7812   I32 i;
7813
7814   if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
7815     croak (\"array reference expected\");
7816
7817   av = (AV *)SvRV (arg);
7818   ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
7819   if (!ret)
7820     croak (\"malloc failed\");
7821
7822   for (i = 0; i <= av_len (av); i++) {
7823     SV **elem = av_fetch (av, i, 0);
7824
7825     if (!elem || !*elem)
7826       croak (\"missing element in list\");
7827
7828     ret[i] = SvPV_nolen (*elem);
7829   }
7830
7831   ret[i] = NULL;
7832
7833   return ret;
7834 }
7835
7836 MODULE = Sys::Guestfs  PACKAGE = Sys::Guestfs
7837
7838 PROTOTYPES: ENABLE
7839
7840 guestfs_h *
7841 _create ()
7842    CODE:
7843       RETVAL = guestfs_create ();
7844       if (!RETVAL)
7845         croak (\"could not create guestfs handle\");
7846       guestfs_set_error_handler (RETVAL, NULL, NULL);
7847  OUTPUT:
7848       RETVAL
7849
7850 void
7851 DESTROY (g)
7852       guestfs_h *g;
7853  PPCODE:
7854       guestfs_close (g);
7855
7856 ";
7857
7858   List.iter (
7859     fun (name, style, _, _, _, _, _) ->
7860       (match fst style with
7861        | RErr -> pr "void\n"
7862        | RInt _ -> pr "SV *\n"
7863        | RInt64 _ -> pr "SV *\n"
7864        | RBool _ -> pr "SV *\n"
7865        | RConstString _ -> pr "SV *\n"
7866        | RConstOptString _ -> pr "SV *\n"
7867        | RString _ -> pr "SV *\n"
7868        | RBufferOut _ -> pr "SV *\n"
7869        | RStringList _
7870        | RStruct _ | RStructList _
7871        | RHashtable _ ->
7872            pr "void\n" (* all lists returned implictly on the stack *)
7873       );
7874       (* Call and arguments. *)
7875       pr "%s " name;
7876       generate_c_call_args ~handle:"g" ~decl:true style;
7877       pr "\n";
7878       pr "      guestfs_h *g;\n";
7879       iteri (
7880         fun i ->
7881           function
7882           | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
7883               pr "      char *%s;\n" n
7884           | OptString n ->
7885               (* http://www.perlmonks.org/?node_id=554277
7886                * Note that the implicit handle argument means we have
7887                * to add 1 to the ST(x) operator.
7888                *)
7889               pr "      char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
7890           | StringList n | DeviceList n -> pr "      char **%s;\n" n
7891           | Bool n -> pr "      int %s;\n" n
7892           | Int n -> pr "      int %s;\n" n
7893           | Int64 n -> pr "      int64_t %s;\n" n
7894       ) (snd style);
7895
7896       let do_cleanups () =
7897         List.iter (
7898           function
7899           | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
7900           | Bool _ | Int _ | Int64 _
7901           | FileIn _ | FileOut _ -> ()
7902           | StringList n | DeviceList n -> pr "      free (%s);\n" n
7903         ) (snd style)
7904       in
7905
7906       (* Code. *)
7907       (match fst style with
7908        | RErr ->
7909            pr "PREINIT:\n";
7910            pr "      int r;\n";
7911            pr " PPCODE:\n";
7912            pr "      r = guestfs_%s " name;
7913            generate_c_call_args ~handle:"g" style;
7914            pr ";\n";
7915            do_cleanups ();
7916            pr "      if (r == -1)\n";
7917            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7918        | RInt n
7919        | RBool n ->
7920            pr "PREINIT:\n";
7921            pr "      int %s;\n" n;
7922            pr "   CODE:\n";
7923            pr "      %s = guestfs_%s " n name;
7924            generate_c_call_args ~handle:"g" style;
7925            pr ";\n";
7926            do_cleanups ();
7927            pr "      if (%s == -1)\n" n;
7928            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7929            pr "      RETVAL = newSViv (%s);\n" n;
7930            pr " OUTPUT:\n";
7931            pr "      RETVAL\n"
7932        | RInt64 n ->
7933            pr "PREINIT:\n";
7934            pr "      int64_t %s;\n" n;
7935            pr "   CODE:\n";
7936            pr "      %s = guestfs_%s " n name;
7937            generate_c_call_args ~handle:"g" style;
7938            pr ";\n";
7939            do_cleanups ();
7940            pr "      if (%s == -1)\n" n;
7941            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7942            pr "      RETVAL = my_newSVll (%s);\n" n;
7943            pr " OUTPUT:\n";
7944            pr "      RETVAL\n"
7945        | RConstString n ->
7946            pr "PREINIT:\n";
7947            pr "      const char *%s;\n" n;
7948            pr "   CODE:\n";
7949            pr "      %s = guestfs_%s " n name;
7950            generate_c_call_args ~handle:"g" style;
7951            pr ";\n";
7952            do_cleanups ();
7953            pr "      if (%s == NULL)\n" n;
7954            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7955            pr "      RETVAL = newSVpv (%s, 0);\n" n;
7956            pr " OUTPUT:\n";
7957            pr "      RETVAL\n"
7958        | RConstOptString n ->
7959            pr "PREINIT:\n";
7960            pr "      const char *%s;\n" n;
7961            pr "   CODE:\n";
7962            pr "      %s = guestfs_%s " n name;
7963            generate_c_call_args ~handle:"g" style;
7964            pr ";\n";
7965            do_cleanups ();
7966            pr "      if (%s == NULL)\n" n;
7967            pr "        RETVAL = &PL_sv_undef;\n";
7968            pr "      else\n";
7969            pr "        RETVAL = newSVpv (%s, 0);\n" n;
7970            pr " OUTPUT:\n";
7971            pr "      RETVAL\n"
7972        | RString n ->
7973            pr "PREINIT:\n";
7974            pr "      char *%s;\n" n;
7975            pr "   CODE:\n";
7976            pr "      %s = guestfs_%s " n name;
7977            generate_c_call_args ~handle:"g" style;
7978            pr ";\n";
7979            do_cleanups ();
7980            pr "      if (%s == NULL)\n" n;
7981            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7982            pr "      RETVAL = newSVpv (%s, 0);\n" n;
7983            pr "      free (%s);\n" n;
7984            pr " OUTPUT:\n";
7985            pr "      RETVAL\n"
7986        | RStringList n | RHashtable n ->
7987            pr "PREINIT:\n";
7988            pr "      char **%s;\n" n;
7989            pr "      int i, n;\n";
7990            pr " PPCODE:\n";
7991            pr "      %s = guestfs_%s " n name;
7992            generate_c_call_args ~handle:"g" style;
7993            pr ";\n";
7994            do_cleanups ();
7995            pr "      if (%s == NULL)\n" n;
7996            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7997            pr "      for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
7998            pr "      EXTEND (SP, n);\n";
7999            pr "      for (i = 0; i < n; ++i) {\n";
8000            pr "        PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
8001            pr "        free (%s[i]);\n" n;
8002            pr "      }\n";
8003            pr "      free (%s);\n" n;
8004        | RStruct (n, typ) ->
8005            let cols = cols_of_struct typ in
8006            generate_perl_struct_code typ cols name style n do_cleanups
8007        | RStructList (n, typ) ->
8008            let cols = cols_of_struct typ in
8009            generate_perl_struct_list_code typ cols name style n do_cleanups
8010        | RBufferOut n ->
8011            pr "PREINIT:\n";
8012            pr "      char *%s;\n" n;
8013            pr "      size_t size;\n";
8014            pr "   CODE:\n";
8015            pr "      %s = guestfs_%s " n name;
8016            generate_c_call_args ~handle:"g" style;
8017            pr ";\n";
8018            do_cleanups ();
8019            pr "      if (%s == NULL)\n" n;
8020            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
8021            pr "      RETVAL = newSVpv (%s, size);\n" n;
8022            pr "      free (%s);\n" n;
8023            pr " OUTPUT:\n";
8024            pr "      RETVAL\n"
8025       );
8026
8027       pr "\n"
8028   ) all_functions
8029
8030 and generate_perl_struct_list_code typ cols name style n do_cleanups =
8031   pr "PREINIT:\n";
8032   pr "      struct guestfs_%s_list *%s;\n" typ n;
8033   pr "      int i;\n";
8034   pr "      HV *hv;\n";
8035   pr " PPCODE:\n";
8036   pr "      %s = guestfs_%s " n name;
8037   generate_c_call_args ~handle:"g" style;
8038   pr ";\n";
8039   do_cleanups ();
8040   pr "      if (%s == NULL)\n" n;
8041   pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
8042   pr "      EXTEND (SP, %s->len);\n" n;
8043   pr "      for (i = 0; i < %s->len; ++i) {\n" n;
8044   pr "        hv = newHV ();\n";
8045   List.iter (
8046     function
8047     | name, FString ->
8048         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
8049           name (String.length name) n name
8050     | name, FUUID ->
8051         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
8052           name (String.length name) n name
8053     | name, FBuffer ->
8054         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
8055           name (String.length name) n name n name
8056     | name, (FBytes|FUInt64) ->
8057         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
8058           name (String.length name) n name
8059     | name, FInt64 ->
8060         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
8061           name (String.length name) n name
8062     | name, (FInt32|FUInt32) ->
8063         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8064           name (String.length name) n name
8065     | name, FChar ->
8066         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
8067           name (String.length name) n name
8068     | name, FOptPercent ->
8069         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8070           name (String.length name) n name
8071   ) cols;
8072   pr "        PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
8073   pr "      }\n";
8074   pr "      guestfs_free_%s_list (%s);\n" typ n
8075
8076 and generate_perl_struct_code typ cols name style n do_cleanups =
8077   pr "PREINIT:\n";
8078   pr "      struct guestfs_%s *%s;\n" typ n;
8079   pr " PPCODE:\n";
8080   pr "      %s = guestfs_%s " n name;
8081   generate_c_call_args ~handle:"g" style;
8082   pr ";\n";
8083   do_cleanups ();
8084   pr "      if (%s == NULL)\n" n;
8085   pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
8086   pr "      EXTEND (SP, 2 * %d);\n" (List.length cols);
8087   List.iter (
8088     fun ((name, _) as col) ->
8089       pr "      PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
8090
8091       match col with
8092       | name, FString ->
8093           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
8094             n name
8095       | name, FBuffer ->
8096           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, %s->%s_len)));\n"
8097             n name n name
8098       | name, FUUID ->
8099           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
8100             n name
8101       | name, (FBytes|FUInt64) ->
8102           pr "      PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
8103             n name
8104       | name, FInt64 ->
8105           pr "      PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
8106             n name
8107       | name, (FInt32|FUInt32) ->
8108           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8109             n name
8110       | name, FChar ->
8111           pr "      PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
8112             n name
8113       | name, FOptPercent ->
8114           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8115             n name
8116   ) cols;
8117   pr "      free (%s);\n" n
8118
8119 (* Generate Sys/Guestfs.pm. *)
8120 and generate_perl_pm () =
8121   generate_header HashStyle LGPLv2;
8122
8123   pr "\
8124 =pod
8125
8126 =head1 NAME
8127
8128 Sys::Guestfs - Perl bindings for libguestfs
8129
8130 =head1 SYNOPSIS
8131
8132  use Sys::Guestfs;
8133
8134  my $h = Sys::Guestfs->new ();
8135  $h->add_drive ('guest.img');
8136  $h->launch ();
8137  $h->mount ('/dev/sda1', '/');
8138  $h->touch ('/hello');
8139  $h->sync ();
8140
8141 =head1 DESCRIPTION
8142
8143 The C<Sys::Guestfs> module provides a Perl XS binding to the
8144 libguestfs API for examining and modifying virtual machine
8145 disk images.
8146
8147 Amongst the things this is good for: making batch configuration
8148 changes to guests, getting disk used/free statistics (see also:
8149 virt-df), migrating between virtualization systems (see also:
8150 virt-p2v), performing partial backups, performing partial guest
8151 clones, cloning guests and changing registry/UUID/hostname info, and
8152 much else besides.
8153
8154 Libguestfs uses Linux kernel and qemu code, and can access any type of
8155 guest filesystem that Linux and qemu can, including but not limited
8156 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8157 schemes, qcow, qcow2, vmdk.
8158
8159 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8160 LVs, what filesystem is in each LV, etc.).  It can also run commands
8161 in the context of the guest.  Also you can access filesystems over FTP.
8162
8163 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
8164 functions for using libguestfs from Perl, including integration
8165 with libvirt.
8166
8167 =head1 ERRORS
8168
8169 All errors turn into calls to C<croak> (see L<Carp(3)>).
8170
8171 =head1 METHODS
8172
8173 =over 4
8174
8175 =cut
8176
8177 package Sys::Guestfs;
8178
8179 use strict;
8180 use warnings;
8181
8182 require XSLoader;
8183 XSLoader::load ('Sys::Guestfs');
8184
8185 =item $h = Sys::Guestfs->new ();
8186
8187 Create a new guestfs handle.
8188
8189 =cut
8190
8191 sub new {
8192   my $proto = shift;
8193   my $class = ref ($proto) || $proto;
8194
8195   my $self = Sys::Guestfs::_create ();
8196   bless $self, $class;
8197   return $self;
8198 }
8199
8200 ";
8201
8202   (* Actions.  We only need to print documentation for these as
8203    * they are pulled in from the XS code automatically.
8204    *)
8205   List.iter (
8206     fun (name, style, _, flags, _, _, longdesc) ->
8207       if not (List.mem NotInDocs flags) then (
8208         let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
8209         pr "=item ";
8210         generate_perl_prototype name style;
8211         pr "\n\n";
8212         pr "%s\n\n" longdesc;
8213         if List.mem ProtocolLimitWarning flags then
8214           pr "%s\n\n" protocol_limit_warning;
8215         if List.mem DangerWillRobinson flags then
8216           pr "%s\n\n" danger_will_robinson;
8217         match deprecation_notice flags with
8218         | None -> ()
8219         | Some txt -> pr "%s\n\n" txt
8220       )
8221   ) all_functions_sorted;
8222
8223   (* End of file. *)
8224   pr "\
8225 =cut
8226
8227 1;
8228
8229 =back
8230
8231 =head1 COPYRIGHT
8232
8233 Copyright (C) 2009 Red Hat Inc.
8234
8235 =head1 LICENSE
8236
8237 Please see the file COPYING.LIB for the full license.
8238
8239 =head1 SEE ALSO
8240
8241 L<guestfs(3)>,
8242 L<guestfish(1)>,
8243 L<http://libguestfs.org>,
8244 L<Sys::Guestfs::Lib(3)>.
8245
8246 =cut
8247 "
8248
8249 and generate_perl_prototype name style =
8250   (match fst style with
8251    | RErr -> ()
8252    | RBool n
8253    | RInt n
8254    | RInt64 n
8255    | RConstString n
8256    | RConstOptString n
8257    | RString n
8258    | RBufferOut n -> pr "$%s = " n
8259    | RStruct (n,_)
8260    | RHashtable n -> pr "%%%s = " n
8261    | RStringList n
8262    | RStructList (n,_) -> pr "@%s = " n
8263   );
8264   pr "$h->%s (" name;
8265   let comma = ref false in
8266   List.iter (
8267     fun arg ->
8268       if !comma then pr ", ";
8269       comma := true;
8270       match arg with
8271       | Pathname n | Device n | Dev_or_Path n | String n
8272       | OptString n | Bool n | Int n | Int64 n | FileIn n | FileOut n ->
8273           pr "$%s" n
8274       | StringList n | DeviceList n ->
8275           pr "\\@%s" n
8276   ) (snd style);
8277   pr ");"
8278
8279 (* Generate Python C module. *)
8280 and generate_python_c () =
8281   generate_header CStyle LGPLv2;
8282
8283   pr "\
8284 #include <Python.h>
8285
8286 #include <stdio.h>
8287 #include <stdlib.h>
8288 #include <assert.h>
8289
8290 #include \"guestfs.h\"
8291
8292 typedef struct {
8293   PyObject_HEAD
8294   guestfs_h *g;
8295 } Pyguestfs_Object;
8296
8297 static guestfs_h *
8298 get_handle (PyObject *obj)
8299 {
8300   assert (obj);
8301   assert (obj != Py_None);
8302   return ((Pyguestfs_Object *) obj)->g;
8303 }
8304
8305 static PyObject *
8306 put_handle (guestfs_h *g)
8307 {
8308   assert (g);
8309   return
8310     PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
8311 }
8312
8313 /* This list should be freed (but not the strings) after use. */
8314 static char **
8315 get_string_list (PyObject *obj)
8316 {
8317   int i, len;
8318   char **r;
8319
8320   assert (obj);
8321
8322   if (!PyList_Check (obj)) {
8323     PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
8324     return NULL;
8325   }
8326
8327   len = PyList_Size (obj);
8328   r = malloc (sizeof (char *) * (len+1));
8329   if (r == NULL) {
8330     PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
8331     return NULL;
8332   }
8333
8334   for (i = 0; i < len; ++i)
8335     r[i] = PyString_AsString (PyList_GetItem (obj, i));
8336   r[len] = NULL;
8337
8338   return r;
8339 }
8340
8341 static PyObject *
8342 put_string_list (char * const * const argv)
8343 {
8344   PyObject *list;
8345   int argc, i;
8346
8347   for (argc = 0; argv[argc] != NULL; ++argc)
8348     ;
8349
8350   list = PyList_New (argc);
8351   for (i = 0; i < argc; ++i)
8352     PyList_SetItem (list, i, PyString_FromString (argv[i]));
8353
8354   return list;
8355 }
8356
8357 static PyObject *
8358 put_table (char * const * const argv)
8359 {
8360   PyObject *list, *item;
8361   int argc, i;
8362
8363   for (argc = 0; argv[argc] != NULL; ++argc)
8364     ;
8365
8366   list = PyList_New (argc >> 1);
8367   for (i = 0; i < argc; i += 2) {
8368     item = PyTuple_New (2);
8369     PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
8370     PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
8371     PyList_SetItem (list, i >> 1, item);
8372   }
8373
8374   return list;
8375 }
8376
8377 static void
8378 free_strings (char **argv)
8379 {
8380   int argc;
8381
8382   for (argc = 0; argv[argc] != NULL; ++argc)
8383     free (argv[argc]);
8384   free (argv);
8385 }
8386
8387 static PyObject *
8388 py_guestfs_create (PyObject *self, PyObject *args)
8389 {
8390   guestfs_h *g;
8391
8392   g = guestfs_create ();
8393   if (g == NULL) {
8394     PyErr_SetString (PyExc_RuntimeError,
8395                      \"guestfs.create: failed to allocate handle\");
8396     return NULL;
8397   }
8398   guestfs_set_error_handler (g, NULL, NULL);
8399   return put_handle (g);
8400 }
8401
8402 static PyObject *
8403 py_guestfs_close (PyObject *self, PyObject *args)
8404 {
8405   PyObject *py_g;
8406   guestfs_h *g;
8407
8408   if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
8409     return NULL;
8410   g = get_handle (py_g);
8411
8412   guestfs_close (g);
8413
8414   Py_INCREF (Py_None);
8415   return Py_None;
8416 }
8417
8418 ";
8419
8420   let emit_put_list_function typ =
8421     pr "static PyObject *\n";
8422     pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
8423     pr "{\n";
8424     pr "  PyObject *list;\n";
8425     pr "  int i;\n";
8426     pr "\n";
8427     pr "  list = PyList_New (%ss->len);\n" typ;
8428     pr "  for (i = 0; i < %ss->len; ++i)\n" typ;
8429     pr "    PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
8430     pr "  return list;\n";
8431     pr "};\n";
8432     pr "\n"
8433   in
8434
8435   (* Structures, turned into Python dictionaries. *)
8436   List.iter (
8437     fun (typ, cols) ->
8438       pr "static PyObject *\n";
8439       pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
8440       pr "{\n";
8441       pr "  PyObject *dict;\n";
8442       pr "\n";
8443       pr "  dict = PyDict_New ();\n";
8444       List.iter (
8445         function
8446         | name, FString ->
8447             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8448             pr "                        PyString_FromString (%s->%s));\n"
8449               typ name
8450         | name, FBuffer ->
8451             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8452             pr "                        PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
8453               typ name typ name
8454         | name, FUUID ->
8455             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8456             pr "                        PyString_FromStringAndSize (%s->%s, 32));\n"
8457               typ name
8458         | name, (FBytes|FUInt64) ->
8459             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8460             pr "                        PyLong_FromUnsignedLongLong (%s->%s));\n"
8461               typ name
8462         | name, FInt64 ->
8463             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8464             pr "                        PyLong_FromLongLong (%s->%s));\n"
8465               typ name
8466         | name, FUInt32 ->
8467             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8468             pr "                        PyLong_FromUnsignedLong (%s->%s));\n"
8469               typ name
8470         | name, FInt32 ->
8471             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8472             pr "                        PyLong_FromLong (%s->%s));\n"
8473               typ name
8474         | name, FOptPercent ->
8475             pr "  if (%s->%s >= 0)\n" typ name;
8476             pr "    PyDict_SetItemString (dict, \"%s\",\n" name;
8477             pr "                          PyFloat_FromDouble ((double) %s->%s));\n"
8478               typ name;
8479             pr "  else {\n";
8480             pr "    Py_INCREF (Py_None);\n";
8481             pr "    PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
8482             pr "  }\n"
8483         | name, FChar ->
8484             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8485             pr "                        PyString_FromStringAndSize (&dirent->%s, 1));\n" name
8486       ) cols;
8487       pr "  return dict;\n";
8488       pr "};\n";
8489       pr "\n";
8490
8491   ) structs;
8492
8493   (* Emit a put_TYPE_list function definition only if that function is used. *)
8494   List.iter (
8495     function
8496     | typ, (RStructListOnly | RStructAndList) ->
8497         (* generate the function for typ *)
8498         emit_put_list_function typ
8499     | typ, _ -> () (* empty *)
8500   ) (rstructs_used_by all_functions);
8501
8502   (* Python wrapper functions. *)
8503   List.iter (
8504     fun (name, style, _, _, _, _, _) ->
8505       pr "static PyObject *\n";
8506       pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
8507       pr "{\n";
8508
8509       pr "  PyObject *py_g;\n";
8510       pr "  guestfs_h *g;\n";
8511       pr "  PyObject *py_r;\n";
8512
8513       let error_code =
8514         match fst style with
8515         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
8516         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8517         | RConstString _ | RConstOptString _ ->
8518             pr "  const char *r;\n"; "NULL"
8519         | RString _ -> pr "  char *r;\n"; "NULL"
8520         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
8521         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
8522         | RStructList (_, typ) ->
8523             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8524         | RBufferOut _ ->
8525             pr "  char *r;\n";
8526             pr "  size_t size;\n";
8527             "NULL" in
8528
8529       List.iter (
8530         function
8531         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8532             pr "  const char *%s;\n" n
8533         | OptString n -> pr "  const char *%s;\n" n
8534         | StringList n | DeviceList n ->
8535             pr "  PyObject *py_%s;\n" n;
8536             pr "  char **%s;\n" n
8537         | Bool n -> pr "  int %s;\n" n
8538         | Int n -> pr "  int %s;\n" n
8539         | Int64 n -> pr "  long long %s;\n" n
8540       ) (snd style);
8541
8542       pr "\n";
8543
8544       (* Convert the parameters. *)
8545       pr "  if (!PyArg_ParseTuple (args, (char *) \"O";
8546       List.iter (
8547         function
8548         | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
8549         | OptString _ -> pr "z"
8550         | StringList _ | DeviceList _ -> pr "O"
8551         | Bool _ -> pr "i" (* XXX Python has booleans? *)
8552         | Int _ -> pr "i"
8553         | Int64 _ -> pr "L" (* XXX Whoever thought it was a good idea to
8554                              * emulate C's int/long/long long in Python?
8555                              *)
8556       ) (snd style);
8557       pr ":guestfs_%s\",\n" name;
8558       pr "                         &py_g";
8559       List.iter (
8560         function
8561         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
8562         | OptString n -> pr ", &%s" n
8563         | StringList n | DeviceList n -> pr ", &py_%s" n
8564         | Bool n -> pr ", &%s" n
8565         | Int n -> pr ", &%s" n
8566         | Int64 n -> pr ", &%s" n
8567       ) (snd style);
8568
8569       pr "))\n";
8570       pr "    return NULL;\n";
8571
8572       pr "  g = get_handle (py_g);\n";
8573       List.iter (
8574         function
8575         | Pathname _ | Device _ | Dev_or_Path _ | String _
8576         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
8577         | StringList n | DeviceList n ->
8578             pr "  %s = get_string_list (py_%s);\n" n n;
8579             pr "  if (!%s) return NULL;\n" n
8580       ) (snd style);
8581
8582       pr "\n";
8583
8584       pr "  r = guestfs_%s " name;
8585       generate_c_call_args ~handle:"g" style;
8586       pr ";\n";
8587
8588       List.iter (
8589         function
8590         | Pathname _ | Device _ | Dev_or_Path _ | String _
8591         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
8592         | StringList n | DeviceList n ->
8593             pr "  free (%s);\n" n
8594       ) (snd style);
8595
8596       pr "  if (r == %s) {\n" error_code;
8597       pr "    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
8598       pr "    return NULL;\n";
8599       pr "  }\n";
8600       pr "\n";
8601
8602       (match fst style with
8603        | RErr ->
8604            pr "  Py_INCREF (Py_None);\n";
8605            pr "  py_r = Py_None;\n"
8606        | RInt _
8607        | RBool _ -> pr "  py_r = PyInt_FromLong ((long) r);\n"
8608        | RInt64 _ -> pr "  py_r = PyLong_FromLongLong (r);\n"
8609        | RConstString _ -> pr "  py_r = PyString_FromString (r);\n"
8610        | RConstOptString _ ->
8611            pr "  if (r)\n";
8612            pr "    py_r = PyString_FromString (r);\n";
8613            pr "  else {\n";
8614            pr "    Py_INCREF (Py_None);\n";
8615            pr "    py_r = Py_None;\n";
8616            pr "  }\n"
8617        | RString _ ->
8618            pr "  py_r = PyString_FromString (r);\n";
8619            pr "  free (r);\n"
8620        | RStringList _ ->
8621            pr "  py_r = put_string_list (r);\n";
8622            pr "  free_strings (r);\n"
8623        | RStruct (_, typ) ->
8624            pr "  py_r = put_%s (r);\n" typ;
8625            pr "  guestfs_free_%s (r);\n" typ
8626        | RStructList (_, typ) ->
8627            pr "  py_r = put_%s_list (r);\n" typ;
8628            pr "  guestfs_free_%s_list (r);\n" typ
8629        | RHashtable n ->
8630            pr "  py_r = put_table (r);\n";
8631            pr "  free_strings (r);\n"
8632        | RBufferOut _ ->
8633            pr "  py_r = PyString_FromStringAndSize (r, size);\n";
8634            pr "  free (r);\n"
8635       );
8636
8637       pr "  return py_r;\n";
8638       pr "}\n";
8639       pr "\n"
8640   ) all_functions;
8641
8642   (* Table of functions. *)
8643   pr "static PyMethodDef methods[] = {\n";
8644   pr "  { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
8645   pr "  { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
8646   List.iter (
8647     fun (name, _, _, _, _, _, _) ->
8648       pr "  { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
8649         name name
8650   ) all_functions;
8651   pr "  { NULL, NULL, 0, NULL }\n";
8652   pr "};\n";
8653   pr "\n";
8654
8655   (* Init function. *)
8656   pr "\
8657 void
8658 initlibguestfsmod (void)
8659 {
8660   static int initialized = 0;
8661
8662   if (initialized) return;
8663   Py_InitModule ((char *) \"libguestfsmod\", methods);
8664   initialized = 1;
8665 }
8666 "
8667
8668 (* Generate Python module. *)
8669 and generate_python_py () =
8670   generate_header HashStyle LGPLv2;
8671
8672   pr "\
8673 u\"\"\"Python bindings for libguestfs
8674
8675 import guestfs
8676 g = guestfs.GuestFS ()
8677 g.add_drive (\"guest.img\")
8678 g.launch ()
8679 parts = g.list_partitions ()
8680
8681 The guestfs module provides a Python binding to the libguestfs API
8682 for examining and modifying virtual machine disk images.
8683
8684 Amongst the things this is good for: making batch configuration
8685 changes to guests, getting disk used/free statistics (see also:
8686 virt-df), migrating between virtualization systems (see also:
8687 virt-p2v), performing partial backups, performing partial guest
8688 clones, cloning guests and changing registry/UUID/hostname info, and
8689 much else besides.
8690
8691 Libguestfs uses Linux kernel and qemu code, and can access any type of
8692 guest filesystem that Linux and qemu can, including but not limited
8693 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8694 schemes, qcow, qcow2, vmdk.
8695
8696 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8697 LVs, what filesystem is in each LV, etc.).  It can also run commands
8698 in the context of the guest.  Also you can access filesystems over FTP.
8699
8700 Errors which happen while using the API are turned into Python
8701 RuntimeError exceptions.
8702
8703 To create a guestfs handle you usually have to perform the following
8704 sequence of calls:
8705
8706 # Create the handle, call add_drive at least once, and possibly
8707 # several times if the guest has multiple block devices:
8708 g = guestfs.GuestFS ()
8709 g.add_drive (\"guest.img\")
8710
8711 # Launch the qemu subprocess and wait for it to become ready:
8712 g.launch ()
8713
8714 # Now you can issue commands, for example:
8715 logvols = g.lvs ()
8716
8717 \"\"\"
8718
8719 import libguestfsmod
8720
8721 class GuestFS:
8722     \"\"\"Instances of this class are libguestfs API handles.\"\"\"
8723
8724     def __init__ (self):
8725         \"\"\"Create a new libguestfs handle.\"\"\"
8726         self._o = libguestfsmod.create ()
8727
8728     def __del__ (self):
8729         libguestfsmod.close (self._o)
8730
8731 ";
8732
8733   List.iter (
8734     fun (name, style, _, flags, _, _, longdesc) ->
8735       pr "    def %s " name;
8736       generate_py_call_args ~handle:"self" (snd style);
8737       pr ":\n";
8738
8739       if not (List.mem NotInDocs flags) then (
8740         let doc = replace_str longdesc "C<guestfs_" "C<g." in
8741         let doc =
8742           match fst style with
8743           | RErr | RInt _ | RInt64 _ | RBool _
8744           | RConstOptString _ | RConstString _
8745           | RString _ | RBufferOut _ -> doc
8746           | RStringList _ ->
8747               doc ^ "\n\nThis function returns a list of strings."
8748           | RStruct (_, typ) ->
8749               doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
8750           | RStructList (_, typ) ->
8751               doc ^ sprintf "\n\nThis function returns a list of %ss.  Each %s is represented as a dictionary." typ typ
8752           | RHashtable _ ->
8753               doc ^ "\n\nThis function returns a dictionary." in
8754         let doc =
8755           if List.mem ProtocolLimitWarning flags then
8756             doc ^ "\n\n" ^ protocol_limit_warning
8757           else doc in
8758         let doc =
8759           if List.mem DangerWillRobinson flags then
8760             doc ^ "\n\n" ^ danger_will_robinson
8761           else doc in
8762         let doc =
8763           match deprecation_notice flags with
8764           | None -> doc
8765           | Some txt -> doc ^ "\n\n" ^ txt in
8766         let doc = pod2text ~width:60 name doc in
8767         let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
8768         let doc = String.concat "\n        " doc in
8769         pr "        u\"\"\"%s\"\"\"\n" doc;
8770       );
8771       pr "        return libguestfsmod.%s " name;
8772       generate_py_call_args ~handle:"self._o" (snd style);
8773       pr "\n";
8774       pr "\n";
8775   ) all_functions
8776
8777 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
8778 and generate_py_call_args ~handle args =
8779   pr "(%s" handle;
8780   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
8781   pr ")"
8782
8783 (* Useful if you need the longdesc POD text as plain text.  Returns a
8784  * list of lines.
8785  *
8786  * Because this is very slow (the slowest part of autogeneration),
8787  * we memoize the results.
8788  *)
8789 and pod2text ~width name longdesc =
8790   let key = width, name, longdesc in
8791   try Hashtbl.find pod2text_memo key
8792   with Not_found ->
8793     let filename, chan = Filename.open_temp_file "gen" ".tmp" in
8794     fprintf chan "=head1 %s\n\n%s\n" name longdesc;
8795     close_out chan;
8796     let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
8797     let chan = open_process_in cmd in
8798     let lines = ref [] in
8799     let rec loop i =
8800       let line = input_line chan in
8801       if i = 1 then             (* discard the first line of output *)
8802         loop (i+1)
8803       else (
8804         let line = triml line in
8805         lines := line :: !lines;
8806         loop (i+1)
8807       ) in
8808     let lines = try loop 1 with End_of_file -> List.rev !lines in
8809     unlink filename;
8810     (match close_process_in chan with
8811      | WEXITED 0 -> ()
8812      | WEXITED i ->
8813          failwithf "pod2text: process exited with non-zero status (%d)" i
8814      | WSIGNALED i | WSTOPPED i ->
8815          failwithf "pod2text: process signalled or stopped by signal %d" i
8816     );
8817     Hashtbl.add pod2text_memo key lines;
8818     pod2text_memo_updated ();
8819     lines
8820
8821 (* Generate ruby bindings. *)
8822 and generate_ruby_c () =
8823   generate_header CStyle LGPLv2;
8824
8825   pr "\
8826 #include <stdio.h>
8827 #include <stdlib.h>
8828
8829 #include <ruby.h>
8830
8831 #include \"guestfs.h\"
8832
8833 #include \"extconf.h\"
8834
8835 /* For Ruby < 1.9 */
8836 #ifndef RARRAY_LEN
8837 #define RARRAY_LEN(r) (RARRAY((r))->len)
8838 #endif
8839
8840 static VALUE m_guestfs;                 /* guestfs module */
8841 static VALUE c_guestfs;                 /* guestfs_h handle */
8842 static VALUE e_Error;                   /* used for all errors */
8843
8844 static void ruby_guestfs_free (void *p)
8845 {
8846   if (!p) return;
8847   guestfs_close ((guestfs_h *) p);
8848 }
8849
8850 static VALUE ruby_guestfs_create (VALUE m)
8851 {
8852   guestfs_h *g;
8853
8854   g = guestfs_create ();
8855   if (!g)
8856     rb_raise (e_Error, \"failed to create guestfs handle\");
8857
8858   /* Don't print error messages to stderr by default. */
8859   guestfs_set_error_handler (g, NULL, NULL);
8860
8861   /* Wrap it, and make sure the close function is called when the
8862    * handle goes away.
8863    */
8864   return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
8865 }
8866
8867 static VALUE ruby_guestfs_close (VALUE gv)
8868 {
8869   guestfs_h *g;
8870   Data_Get_Struct (gv, guestfs_h, g);
8871
8872   ruby_guestfs_free (g);
8873   DATA_PTR (gv) = NULL;
8874
8875   return Qnil;
8876 }
8877
8878 ";
8879
8880   List.iter (
8881     fun (name, style, _, _, _, _, _) ->
8882       pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
8883       List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
8884       pr ")\n";
8885       pr "{\n";
8886       pr "  guestfs_h *g;\n";
8887       pr "  Data_Get_Struct (gv, guestfs_h, g);\n";
8888       pr "  if (!g)\n";
8889       pr "    rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
8890         name;
8891       pr "\n";
8892
8893       List.iter (
8894         function
8895         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8896             pr "  Check_Type (%sv, T_STRING);\n" n;
8897             pr "  const char *%s = StringValueCStr (%sv);\n" n n;
8898             pr "  if (!%s)\n" n;
8899             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
8900             pr "              \"%s\", \"%s\");\n" n name
8901         | OptString n ->
8902             pr "  const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
8903         | StringList n | DeviceList n ->
8904             pr "  char **%s;\n" n;
8905             pr "  Check_Type (%sv, T_ARRAY);\n" n;
8906             pr "  {\n";
8907             pr "    int i, len;\n";
8908             pr "    len = RARRAY_LEN (%sv);\n" n;
8909             pr "    %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
8910               n;
8911             pr "    for (i = 0; i < len; ++i) {\n";
8912             pr "      VALUE v = rb_ary_entry (%sv, i);\n" n;
8913             pr "      %s[i] = StringValueCStr (v);\n" n;
8914             pr "    }\n";
8915             pr "    %s[len] = NULL;\n" n;
8916             pr "  }\n";
8917         | Bool n ->
8918             pr "  int %s = RTEST (%sv);\n" n n
8919         | Int n ->
8920             pr "  int %s = NUM2INT (%sv);\n" n n
8921         | Int64 n ->
8922             pr "  long long %s = NUM2LL (%sv);\n" n n
8923       ) (snd style);
8924       pr "\n";
8925
8926       let error_code =
8927         match fst style with
8928         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
8929         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8930         | RConstString _ | RConstOptString _ ->
8931             pr "  const char *r;\n"; "NULL"
8932         | RString _ -> pr "  char *r;\n"; "NULL"
8933         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
8934         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
8935         | RStructList (_, typ) ->
8936             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8937         | RBufferOut _ ->
8938             pr "  char *r;\n";
8939             pr "  size_t size;\n";
8940             "NULL" in
8941       pr "\n";
8942
8943       pr "  r = guestfs_%s " name;
8944       generate_c_call_args ~handle:"g" style;
8945       pr ";\n";
8946
8947       List.iter (
8948         function
8949         | Pathname _ | Device _ | Dev_or_Path _ | String _
8950         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
8951         | StringList n | DeviceList n ->
8952             pr "  free (%s);\n" n
8953       ) (snd style);
8954
8955       pr "  if (r == %s)\n" error_code;
8956       pr "    rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
8957       pr "\n";
8958
8959       (match fst style with
8960        | RErr ->
8961            pr "  return Qnil;\n"
8962        | RInt _ | RBool _ ->
8963            pr "  return INT2NUM (r);\n"
8964        | RInt64 _ ->
8965            pr "  return ULL2NUM (r);\n"
8966        | RConstString _ ->
8967            pr "  return rb_str_new2 (r);\n";
8968        | RConstOptString _ ->
8969            pr "  if (r)\n";
8970            pr "    return rb_str_new2 (r);\n";
8971            pr "  else\n";
8972            pr "    return Qnil;\n";
8973        | RString _ ->
8974            pr "  VALUE rv = rb_str_new2 (r);\n";
8975            pr "  free (r);\n";
8976            pr "  return rv;\n";
8977        | RStringList _ ->
8978            pr "  int i, len = 0;\n";
8979            pr "  for (i = 0; r[i] != NULL; ++i) len++;\n";
8980            pr "  VALUE rv = rb_ary_new2 (len);\n";
8981            pr "  for (i = 0; r[i] != NULL; ++i) {\n";
8982            pr "    rb_ary_push (rv, rb_str_new2 (r[i]));\n";
8983            pr "    free (r[i]);\n";
8984            pr "  }\n";
8985            pr "  free (r);\n";
8986            pr "  return rv;\n"
8987        | RStruct (_, typ) ->
8988            let cols = cols_of_struct typ in
8989            generate_ruby_struct_code typ cols
8990        | RStructList (_, typ) ->
8991            let cols = cols_of_struct typ in
8992            generate_ruby_struct_list_code typ cols
8993        | RHashtable _ ->
8994            pr "  VALUE rv = rb_hash_new ();\n";
8995            pr "  int i;\n";
8996            pr "  for (i = 0; r[i] != NULL; i+=2) {\n";
8997            pr "    rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
8998            pr "    free (r[i]);\n";
8999            pr "    free (r[i+1]);\n";
9000            pr "  }\n";
9001            pr "  free (r);\n";
9002            pr "  return rv;\n"
9003        | RBufferOut _ ->
9004            pr "  VALUE rv = rb_str_new (r, size);\n";
9005            pr "  free (r);\n";
9006            pr "  return rv;\n";
9007       );
9008
9009       pr "}\n";
9010       pr "\n"
9011   ) all_functions;
9012
9013   pr "\
9014 /* Initialize the module. */
9015 void Init__guestfs ()
9016 {
9017   m_guestfs = rb_define_module (\"Guestfs\");
9018   c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
9019   e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
9020
9021   rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
9022   rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
9023
9024 ";
9025   (* Define the rest of the methods. *)
9026   List.iter (
9027     fun (name, style, _, _, _, _, _) ->
9028       pr "  rb_define_method (c_guestfs, \"%s\",\n" name;
9029       pr "        ruby_guestfs_%s, %d);\n" name (List.length (snd style))
9030   ) all_functions;
9031
9032   pr "}\n"
9033
9034 (* Ruby code to return a struct. *)
9035 and generate_ruby_struct_code typ cols =
9036   pr "  VALUE rv = rb_hash_new ();\n";
9037   List.iter (
9038     function
9039     | name, FString ->
9040         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
9041     | name, FBuffer ->
9042         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
9043     | name, FUUID ->
9044         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
9045     | name, (FBytes|FUInt64) ->
9046         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9047     | name, FInt64 ->
9048         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
9049     | name, FUInt32 ->
9050         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
9051     | name, FInt32 ->
9052         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
9053     | name, FOptPercent ->
9054         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
9055     | name, FChar -> (* XXX wrong? *)
9056         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9057   ) cols;
9058   pr "  guestfs_free_%s (r);\n" typ;
9059   pr "  return rv;\n"
9060
9061 (* Ruby code to return a struct list. *)
9062 and generate_ruby_struct_list_code typ cols =
9063   pr "  VALUE rv = rb_ary_new2 (r->len);\n";
9064   pr "  int i;\n";
9065   pr "  for (i = 0; i < r->len; ++i) {\n";
9066   pr "    VALUE hv = rb_hash_new ();\n";
9067   List.iter (
9068     function
9069     | name, FString ->
9070         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
9071     | name, FBuffer ->
9072         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
9073     | name, FUUID ->
9074         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
9075     | name, (FBytes|FUInt64) ->
9076         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9077     | name, FInt64 ->
9078         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
9079     | name, FUInt32 ->
9080         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
9081     | name, FInt32 ->
9082         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
9083     | name, FOptPercent ->
9084         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
9085     | name, FChar -> (* XXX wrong? *)
9086         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9087   ) cols;
9088   pr "    rb_ary_push (rv, hv);\n";
9089   pr "  }\n";
9090   pr "  guestfs_free_%s_list (r);\n" typ;
9091   pr "  return rv;\n"
9092
9093 (* Generate Java bindings GuestFS.java file. *)
9094 and generate_java_java () =
9095   generate_header CStyle LGPLv2;
9096
9097   pr "\
9098 package com.redhat.et.libguestfs;
9099
9100 import java.util.HashMap;
9101 import com.redhat.et.libguestfs.LibGuestFSException;
9102 import com.redhat.et.libguestfs.PV;
9103 import com.redhat.et.libguestfs.VG;
9104 import com.redhat.et.libguestfs.LV;
9105 import com.redhat.et.libguestfs.Stat;
9106 import com.redhat.et.libguestfs.StatVFS;
9107 import com.redhat.et.libguestfs.IntBool;
9108 import com.redhat.et.libguestfs.Dirent;
9109
9110 /**
9111  * The GuestFS object is a libguestfs handle.
9112  *
9113  * @author rjones
9114  */
9115 public class GuestFS {
9116   // Load the native code.
9117   static {
9118     System.loadLibrary (\"guestfs_jni\");
9119   }
9120
9121   /**
9122    * The native guestfs_h pointer.
9123    */
9124   long g;
9125
9126   /**
9127    * Create a libguestfs handle.
9128    *
9129    * @throws LibGuestFSException
9130    */
9131   public GuestFS () throws LibGuestFSException
9132   {
9133     g = _create ();
9134   }
9135   private native long _create () throws LibGuestFSException;
9136
9137   /**
9138    * Close a libguestfs handle.
9139    *
9140    * You can also leave handles to be collected by the garbage
9141    * collector, but this method ensures that the resources used
9142    * by the handle are freed up immediately.  If you call any
9143    * other methods after closing the handle, you will get an
9144    * exception.
9145    *
9146    * @throws LibGuestFSException
9147    */
9148   public void close () throws LibGuestFSException
9149   {
9150     if (g != 0)
9151       _close (g);
9152     g = 0;
9153   }
9154   private native void _close (long g) throws LibGuestFSException;
9155
9156   public void finalize () throws LibGuestFSException
9157   {
9158     close ();
9159   }
9160
9161 ";
9162
9163   List.iter (
9164     fun (name, style, _, flags, _, shortdesc, longdesc) ->
9165       if not (List.mem NotInDocs flags); then (
9166         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9167         let doc =
9168           if List.mem ProtocolLimitWarning flags then
9169             doc ^ "\n\n" ^ protocol_limit_warning
9170           else doc in
9171         let doc =
9172           if List.mem DangerWillRobinson flags then
9173             doc ^ "\n\n" ^ danger_will_robinson
9174           else doc in
9175         let doc =
9176           match deprecation_notice flags with
9177           | None -> doc
9178           | Some txt -> doc ^ "\n\n" ^ txt in
9179         let doc = pod2text ~width:60 name doc in
9180         let doc = List.map (            (* RHBZ#501883 *)
9181           function
9182           | "" -> "<p>"
9183           | nonempty -> nonempty
9184         ) doc in
9185         let doc = String.concat "\n   * " doc in
9186
9187         pr "  /**\n";
9188         pr "   * %s\n" shortdesc;
9189         pr "   * <p>\n";
9190         pr "   * %s\n" doc;
9191         pr "   * @throws LibGuestFSException\n";
9192         pr "   */\n";
9193         pr "  ";
9194       );
9195       generate_java_prototype ~public:true ~semicolon:false name style;
9196       pr "\n";
9197       pr "  {\n";
9198       pr "    if (g == 0)\n";
9199       pr "      throw new LibGuestFSException (\"%s: handle is closed\");\n"
9200         name;
9201       pr "    ";
9202       if fst style <> RErr then pr "return ";
9203       pr "_%s " name;
9204       generate_java_call_args ~handle:"g" (snd style);
9205       pr ";\n";
9206       pr "  }\n";
9207       pr "  ";
9208       generate_java_prototype ~privat:true ~native:true name style;
9209       pr "\n";
9210       pr "\n";
9211   ) all_functions;
9212
9213   pr "}\n"
9214
9215 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
9216 and generate_java_call_args ~handle args =
9217   pr "(%s" handle;
9218   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9219   pr ")"
9220
9221 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
9222     ?(semicolon=true) name style =
9223   if privat then pr "private ";
9224   if public then pr "public ";
9225   if native then pr "native ";
9226
9227   (* return type *)
9228   (match fst style with
9229    | RErr -> pr "void ";
9230    | RInt _ -> pr "int ";
9231    | RInt64 _ -> pr "long ";
9232    | RBool _ -> pr "boolean ";
9233    | RConstString _ | RConstOptString _ | RString _
9234    | RBufferOut _ -> pr "String ";
9235    | RStringList _ -> pr "String[] ";
9236    | RStruct (_, typ) ->
9237        let name = java_name_of_struct typ in
9238        pr "%s " name;
9239    | RStructList (_, typ) ->
9240        let name = java_name_of_struct typ in
9241        pr "%s[] " name;
9242    | RHashtable _ -> pr "HashMap<String,String> ";
9243   );
9244
9245   if native then pr "_%s " name else pr "%s " name;
9246   pr "(";
9247   let needs_comma = ref false in
9248   if native then (
9249     pr "long g";
9250     needs_comma := true
9251   );
9252
9253   (* args *)
9254   List.iter (
9255     fun arg ->
9256       if !needs_comma then pr ", ";
9257       needs_comma := true;
9258
9259       match arg with
9260       | Pathname n
9261       | Device n | Dev_or_Path n
9262       | String n
9263       | OptString n
9264       | FileIn n
9265       | FileOut n ->
9266           pr "String %s" n
9267       | StringList n | DeviceList n ->
9268           pr "String[] %s" n
9269       | Bool n ->
9270           pr "boolean %s" n
9271       | Int n ->
9272           pr "int %s" n
9273       | Int64 n ->
9274           pr "long %s" n
9275   ) (snd style);
9276
9277   pr ")\n";
9278   pr "    throws LibGuestFSException";
9279   if semicolon then pr ";"
9280
9281 and generate_java_struct jtyp cols =
9282   generate_header CStyle LGPLv2;
9283
9284   pr "\
9285 package com.redhat.et.libguestfs;
9286
9287 /**
9288  * Libguestfs %s structure.
9289  *
9290  * @author rjones
9291  * @see GuestFS
9292  */
9293 public class %s {
9294 " jtyp jtyp;
9295
9296   List.iter (
9297     function
9298     | name, FString
9299     | name, FUUID
9300     | name, FBuffer -> pr "  public String %s;\n" name
9301     | name, (FBytes|FUInt64|FInt64) -> pr "  public long %s;\n" name
9302     | name, (FUInt32|FInt32) -> pr "  public int %s;\n" name
9303     | name, FChar -> pr "  public char %s;\n" name
9304     | name, FOptPercent ->
9305         pr "  /* The next field is [0..100] or -1 meaning 'not present': */\n";
9306         pr "  public float %s;\n" name
9307   ) cols;
9308
9309   pr "}\n"
9310
9311 and generate_java_c () =
9312   generate_header CStyle LGPLv2;
9313
9314   pr "\
9315 #include <stdio.h>
9316 #include <stdlib.h>
9317 #include <string.h>
9318
9319 #include \"com_redhat_et_libguestfs_GuestFS.h\"
9320 #include \"guestfs.h\"
9321
9322 /* Note that this function returns.  The exception is not thrown
9323  * until after the wrapper function returns.
9324  */
9325 static void
9326 throw_exception (JNIEnv *env, const char *msg)
9327 {
9328   jclass cl;
9329   cl = (*env)->FindClass (env,
9330                           \"com/redhat/et/libguestfs/LibGuestFSException\");
9331   (*env)->ThrowNew (env, cl, msg);
9332 }
9333
9334 JNIEXPORT jlong JNICALL
9335 Java_com_redhat_et_libguestfs_GuestFS__1create
9336   (JNIEnv *env, jobject obj)
9337 {
9338   guestfs_h *g;
9339
9340   g = guestfs_create ();
9341   if (g == NULL) {
9342     throw_exception (env, \"GuestFS.create: failed to allocate handle\");
9343     return 0;
9344   }
9345   guestfs_set_error_handler (g, NULL, NULL);
9346   return (jlong) (long) g;
9347 }
9348
9349 JNIEXPORT void JNICALL
9350 Java_com_redhat_et_libguestfs_GuestFS__1close
9351   (JNIEnv *env, jobject obj, jlong jg)
9352 {
9353   guestfs_h *g = (guestfs_h *) (long) jg;
9354   guestfs_close (g);
9355 }
9356
9357 ";
9358
9359   List.iter (
9360     fun (name, style, _, _, _, _, _) ->
9361       pr "JNIEXPORT ";
9362       (match fst style with
9363        | RErr -> pr "void ";
9364        | RInt _ -> pr "jint ";
9365        | RInt64 _ -> pr "jlong ";
9366        | RBool _ -> pr "jboolean ";
9367        | RConstString _ | RConstOptString _ | RString _
9368        | RBufferOut _ -> pr "jstring ";
9369        | RStruct _ | RHashtable _ ->
9370            pr "jobject ";
9371        | RStringList _ | RStructList _ ->
9372            pr "jobjectArray ";
9373       );
9374       pr "JNICALL\n";
9375       pr "Java_com_redhat_et_libguestfs_GuestFS_";
9376       pr "%s" (replace_str ("_" ^ name) "_" "_1");
9377       pr "\n";
9378       pr "  (JNIEnv *env, jobject obj, jlong jg";
9379       List.iter (
9380         function
9381         | Pathname n
9382         | Device n | Dev_or_Path n
9383         | String n
9384         | OptString n
9385         | FileIn n
9386         | FileOut n ->
9387             pr ", jstring j%s" n
9388         | StringList n | DeviceList n ->
9389             pr ", jobjectArray j%s" n
9390         | Bool n ->
9391             pr ", jboolean j%s" n
9392         | Int n ->
9393             pr ", jint j%s" n
9394         | Int64 n ->
9395             pr ", jlong j%s" n
9396       ) (snd style);
9397       pr ")\n";
9398       pr "{\n";
9399       pr "  guestfs_h *g = (guestfs_h *) (long) jg;\n";
9400       let error_code, no_ret =
9401         match fst style with
9402         | RErr -> pr "  int r;\n"; "-1", ""
9403         | RBool _
9404         | RInt _ -> pr "  int r;\n"; "-1", "0"
9405         | RInt64 _ -> pr "  int64_t r;\n"; "-1", "0"
9406         | RConstString _ -> pr "  const char *r;\n"; "NULL", "NULL"
9407         | RConstOptString _ -> pr "  const char *r;\n"; "NULL", "NULL"
9408         | RString _ ->
9409             pr "  jstring jr;\n";
9410             pr "  char *r;\n"; "NULL", "NULL"
9411         | RStringList _ ->
9412             pr "  jobjectArray jr;\n";
9413             pr "  int r_len;\n";
9414             pr "  jclass cl;\n";
9415             pr "  jstring jstr;\n";
9416             pr "  char **r;\n"; "NULL", "NULL"
9417         | RStruct (_, typ) ->
9418             pr "  jobject jr;\n";
9419             pr "  jclass cl;\n";
9420             pr "  jfieldID fl;\n";
9421             pr "  struct guestfs_%s *r;\n" typ; "NULL", "NULL"
9422         | RStructList (_, typ) ->
9423             pr "  jobjectArray jr;\n";
9424             pr "  jclass cl;\n";
9425             pr "  jfieldID fl;\n";
9426             pr "  jobject jfl;\n";
9427             pr "  struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
9428         | RHashtable _ -> pr "  char **r;\n"; "NULL", "NULL"
9429         | RBufferOut _ ->
9430             pr "  jstring jr;\n";
9431             pr "  char *r;\n";
9432             pr "  size_t size;\n";
9433             "NULL", "NULL" in
9434       List.iter (
9435         function
9436         | Pathname n
9437         | Device n | Dev_or_Path n
9438         | String n
9439         | OptString n
9440         | FileIn n
9441         | FileOut n ->
9442             pr "  const char *%s;\n" n
9443         | StringList n | DeviceList n ->
9444             pr "  int %s_len;\n" n;
9445             pr "  const char **%s;\n" n
9446         | Bool n
9447         | Int n ->
9448             pr "  int %s;\n" n
9449         | Int64 n ->
9450             pr "  int64_t %s;\n" n
9451       ) (snd style);
9452
9453       let needs_i =
9454         (match fst style with
9455          | RStringList _ | RStructList _ -> true
9456          | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
9457          | RConstOptString _
9458          | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
9459           List.exists (function
9460                        | StringList _ -> true
9461                        | DeviceList _ -> true
9462                        | _ -> false) (snd style) in
9463       if needs_i then
9464         pr "  int i;\n";
9465
9466       pr "\n";
9467
9468       (* Get the parameters. *)
9469       List.iter (
9470         function
9471         | Pathname n
9472         | Device n | Dev_or_Path n
9473         | String n
9474         | FileIn n
9475         | FileOut n ->
9476             pr "  %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
9477         | OptString n ->
9478             (* This is completely undocumented, but Java null becomes
9479              * a NULL parameter.
9480              *)
9481             pr "  %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
9482         | StringList n | DeviceList n ->
9483             pr "  %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
9484             pr "  %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
9485             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
9486             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
9487               n;
9488             pr "    %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
9489             pr "  }\n";
9490             pr "  %s[%s_len] = NULL;\n" n n;
9491         | Bool n
9492         | Int n
9493         | Int64 n ->
9494             pr "  %s = j%s;\n" n n
9495       ) (snd style);
9496
9497       (* Make the call. *)
9498       pr "  r = guestfs_%s " name;
9499       generate_c_call_args ~handle:"g" style;
9500       pr ";\n";
9501
9502       (* Release the parameters. *)
9503       List.iter (
9504         function
9505         | Pathname n
9506         | Device n | Dev_or_Path n
9507         | String n
9508         | FileIn n
9509         | FileOut n ->
9510             pr "  (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
9511         | OptString n ->
9512             pr "  if (j%s)\n" n;
9513             pr "    (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
9514         | StringList n | DeviceList n ->
9515             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
9516             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
9517               n;
9518             pr "    (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
9519             pr "  }\n";
9520             pr "  free (%s);\n" n
9521         | Bool n
9522         | Int n
9523         | Int64 n -> ()
9524       ) (snd style);
9525
9526       (* Check for errors. *)
9527       pr "  if (r == %s) {\n" error_code;
9528       pr "    throw_exception (env, guestfs_last_error (g));\n";
9529       pr "    return %s;\n" no_ret;
9530       pr "  }\n";
9531
9532       (* Return value. *)
9533       (match fst style with
9534        | RErr -> ()
9535        | RInt _ -> pr "  return (jint) r;\n"
9536        | RBool _ -> pr "  return (jboolean) r;\n"
9537        | RInt64 _ -> pr "  return (jlong) r;\n"
9538        | RConstString _ -> pr "  return (*env)->NewStringUTF (env, r);\n"
9539        | RConstOptString _ ->
9540            pr "  return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
9541        | RString _ ->
9542            pr "  jr = (*env)->NewStringUTF (env, r);\n";
9543            pr "  free (r);\n";
9544            pr "  return jr;\n"
9545        | RStringList _ ->
9546            pr "  for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
9547            pr "  cl = (*env)->FindClass (env, \"java/lang/String\");\n";
9548            pr "  jstr = (*env)->NewStringUTF (env, \"\");\n";
9549            pr "  jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
9550            pr "  for (i = 0; i < r_len; ++i) {\n";
9551            pr "    jstr = (*env)->NewStringUTF (env, r[i]);\n";
9552            pr "    (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
9553            pr "    free (r[i]);\n";
9554            pr "  }\n";
9555            pr "  free (r);\n";
9556            pr "  return jr;\n"
9557        | RStruct (_, typ) ->
9558            let jtyp = java_name_of_struct typ in
9559            let cols = cols_of_struct typ in
9560            generate_java_struct_return typ jtyp cols
9561        | RStructList (_, typ) ->
9562            let jtyp = java_name_of_struct typ in
9563            let cols = cols_of_struct typ in
9564            generate_java_struct_list_return typ jtyp cols
9565        | RHashtable _ ->
9566            (* XXX *)
9567            pr "  throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
9568            pr "  return NULL;\n"
9569        | RBufferOut _ ->
9570            pr "  jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
9571            pr "  free (r);\n";
9572            pr "  return jr;\n"
9573       );
9574
9575       pr "}\n";
9576       pr "\n"
9577   ) all_functions
9578
9579 and generate_java_struct_return typ jtyp cols =
9580   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
9581   pr "  jr = (*env)->AllocObject (env, cl);\n";
9582   List.iter (
9583     function
9584     | name, FString ->
9585         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9586         pr "  (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
9587     | name, FUUID ->
9588         pr "  {\n";
9589         pr "    char s[33];\n";
9590         pr "    memcpy (s, r->%s, 32);\n" name;
9591         pr "    s[32] = 0;\n";
9592         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9593         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
9594         pr "  }\n";
9595     | name, FBuffer ->
9596         pr "  {\n";
9597         pr "    int len = r->%s_len;\n" name;
9598         pr "    char s[len+1];\n";
9599         pr "    memcpy (s, r->%s, len);\n" name;
9600         pr "    s[len] = 0;\n";
9601         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9602         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
9603         pr "  }\n";
9604     | name, (FBytes|FUInt64|FInt64) ->
9605         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
9606         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
9607     | name, (FUInt32|FInt32) ->
9608         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
9609         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
9610     | name, FOptPercent ->
9611         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
9612         pr "  (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
9613     | name, FChar ->
9614         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
9615         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
9616   ) cols;
9617   pr "  free (r);\n";
9618   pr "  return jr;\n"
9619
9620 and generate_java_struct_list_return typ jtyp cols =
9621   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
9622   pr "  jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
9623   pr "  for (i = 0; i < r->len; ++i) {\n";
9624   pr "    jfl = (*env)->AllocObject (env, cl);\n";
9625   List.iter (
9626     function
9627     | name, FString ->
9628         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9629         pr "    (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
9630     | name, FUUID ->
9631         pr "    {\n";
9632         pr "      char s[33];\n";
9633         pr "      memcpy (s, r->val[i].%s, 32);\n" name;
9634         pr "      s[32] = 0;\n";
9635         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9636         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
9637         pr "    }\n";
9638     | name, FBuffer ->
9639         pr "    {\n";
9640         pr "      int len = r->val[i].%s_len;\n" name;
9641         pr "      char s[len+1];\n";
9642         pr "      memcpy (s, r->val[i].%s, len);\n" name;
9643         pr "      s[len] = 0;\n";
9644         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9645         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
9646         pr "    }\n";
9647     | name, (FBytes|FUInt64|FInt64) ->
9648         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
9649         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
9650     | name, (FUInt32|FInt32) ->
9651         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
9652         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
9653     | name, FOptPercent ->
9654         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
9655         pr "    (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
9656     | name, FChar ->
9657         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
9658         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
9659   ) cols;
9660   pr "    (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
9661   pr "  }\n";
9662   pr "  guestfs_free_%s_list (r);\n" typ;
9663   pr "  return jr;\n"
9664
9665 and generate_java_makefile_inc () =
9666   generate_header HashStyle GPLv2;
9667
9668   pr "java_built_sources = \\\n";
9669   List.iter (
9670     fun (typ, jtyp) ->
9671         pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
9672   ) java_structs;
9673   pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
9674
9675 and generate_haskell_hs () =
9676   generate_header HaskellStyle LGPLv2;
9677
9678   (* XXX We only know how to generate partial FFI for Haskell
9679    * at the moment.  Please help out!
9680    *)
9681   let can_generate style =
9682     match style with
9683     | RErr, _
9684     | RInt _, _
9685     | RInt64 _, _ -> true
9686     | RBool _, _
9687     | RConstString _, _
9688     | RConstOptString _, _
9689     | RString _, _
9690     | RStringList _, _
9691     | RStruct _, _
9692     | RStructList _, _
9693     | RHashtable _, _
9694     | RBufferOut _, _ -> false in
9695
9696   pr "\
9697 {-# INCLUDE <guestfs.h> #-}
9698 {-# LANGUAGE ForeignFunctionInterface #-}
9699
9700 module Guestfs (
9701   create";
9702
9703   (* List out the names of the actions we want to export. *)
9704   List.iter (
9705     fun (name, style, _, _, _, _, _) ->
9706       if can_generate style then pr ",\n  %s" name
9707   ) all_functions;
9708
9709   pr "
9710   ) where
9711
9712 -- Unfortunately some symbols duplicate ones already present
9713 -- in Prelude.  We don't know which, so we hard-code a list
9714 -- here.
9715 import Prelude hiding (truncate)
9716
9717 import Foreign
9718 import Foreign.C
9719 import Foreign.C.Types
9720 import IO
9721 import Control.Exception
9722 import Data.Typeable
9723
9724 data GuestfsS = GuestfsS            -- represents the opaque C struct
9725 type GuestfsP = Ptr GuestfsS        -- guestfs_h *
9726 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
9727
9728 -- XXX define properly later XXX
9729 data PV = PV
9730 data VG = VG
9731 data LV = LV
9732 data IntBool = IntBool
9733 data Stat = Stat
9734 data StatVFS = StatVFS
9735 data Hashtable = Hashtable
9736
9737 foreign import ccall unsafe \"guestfs_create\" c_create
9738   :: IO GuestfsP
9739 foreign import ccall unsafe \"&guestfs_close\" c_close
9740   :: FunPtr (GuestfsP -> IO ())
9741 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
9742   :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
9743
9744 create :: IO GuestfsH
9745 create = do
9746   p <- c_create
9747   c_set_error_handler p nullPtr nullPtr
9748   h <- newForeignPtr c_close p
9749   return h
9750
9751 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
9752   :: GuestfsP -> IO CString
9753
9754 -- last_error :: GuestfsH -> IO (Maybe String)
9755 -- last_error h = do
9756 --   str <- withForeignPtr h (\\p -> c_last_error p)
9757 --   maybePeek peekCString str
9758
9759 last_error :: GuestfsH -> IO (String)
9760 last_error h = do
9761   str <- withForeignPtr h (\\p -> c_last_error p)
9762   if (str == nullPtr)
9763     then return \"no error\"
9764     else peekCString str
9765
9766 ";
9767
9768   (* Generate wrappers for each foreign function. *)
9769   List.iter (
9770     fun (name, style, _, _, _, _, _) ->
9771       if can_generate style then (
9772         pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
9773         pr "  :: ";
9774         generate_haskell_prototype ~handle:"GuestfsP" style;
9775         pr "\n";
9776         pr "\n";
9777         pr "%s :: " name;
9778         generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
9779         pr "\n";
9780         pr "%s %s = do\n" name
9781           (String.concat " " ("h" :: List.map name_of_argt (snd style)));
9782         pr "  r <- ";
9783         (* Convert pointer arguments using with* functions. *)
9784         List.iter (
9785           function
9786           | FileIn n
9787           | FileOut n
9788           | Pathname n | Device n | Dev_or_Path n | String n -> pr "withCString %s $ \\%s -> " n n
9789           | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
9790           | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
9791           | Bool _ | Int _ | Int64 _ -> ()
9792         ) (snd style);
9793         (* Convert integer arguments. *)
9794         let args =
9795           List.map (
9796             function
9797             | Bool n -> sprintf "(fromBool %s)" n
9798             | Int n -> sprintf "(fromIntegral %s)" n
9799             | Int64 n -> sprintf "(fromIntegral %s)" n
9800             | FileIn n | FileOut n
9801             | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
9802           ) (snd style) in
9803         pr "withForeignPtr h (\\p -> c_%s %s)\n" name
9804           (String.concat " " ("p" :: args));
9805         (match fst style with
9806          | RErr | RInt _ | RInt64 _ | RBool _ ->
9807              pr "  if (r == -1)\n";
9808              pr "    then do\n";
9809              pr "      err <- last_error h\n";
9810              pr "      fail err\n";
9811          | RConstString _ | RConstOptString _ | RString _
9812          | RStringList _ | RStruct _
9813          | RStructList _ | RHashtable _ | RBufferOut _ ->
9814              pr "  if (r == nullPtr)\n";
9815              pr "    then do\n";
9816              pr "      err <- last_error h\n";
9817              pr "      fail err\n";
9818         );
9819         (match fst style with
9820          | RErr ->
9821              pr "    else return ()\n"
9822          | RInt _ ->
9823              pr "    else return (fromIntegral r)\n"
9824          | RInt64 _ ->
9825              pr "    else return (fromIntegral r)\n"
9826          | RBool _ ->
9827              pr "    else return (toBool r)\n"
9828          | RConstString _
9829          | RConstOptString _
9830          | RString _
9831          | RStringList _
9832          | RStruct _
9833          | RStructList _
9834          | RHashtable _
9835          | RBufferOut _ ->
9836              pr "    else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
9837         );
9838         pr "\n";
9839       )
9840   ) all_functions
9841
9842 and generate_haskell_prototype ~handle ?(hs = false) style =
9843   pr "%s -> " handle;
9844   let string = if hs then "String" else "CString" in
9845   let int = if hs then "Int" else "CInt" in
9846   let bool = if hs then "Bool" else "CInt" in
9847   let int64 = if hs then "Integer" else "Int64" in
9848   List.iter (
9849     fun arg ->
9850       (match arg with
9851        | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
9852        | OptString _ -> if hs then pr "Maybe String" else pr "CString"
9853        | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
9854        | Bool _ -> pr "%s" bool
9855        | Int _ -> pr "%s" int
9856        | Int64 _ -> pr "%s" int
9857        | FileIn _ -> pr "%s" string
9858        | FileOut _ -> pr "%s" string
9859       );
9860       pr " -> ";
9861   ) (snd style);
9862   pr "IO (";
9863   (match fst style with
9864    | RErr -> if not hs then pr "CInt"
9865    | RInt _ -> pr "%s" int
9866    | RInt64 _ -> pr "%s" int64
9867    | RBool _ -> pr "%s" bool
9868    | RConstString _ -> pr "%s" string
9869    | RConstOptString _ -> pr "Maybe %s" string
9870    | RString _ -> pr "%s" string
9871    | RStringList _ -> pr "[%s]" string
9872    | RStruct (_, typ) ->
9873        let name = java_name_of_struct typ in
9874        pr "%s" name
9875    | RStructList (_, typ) ->
9876        let name = java_name_of_struct typ in
9877        pr "[%s]" name
9878    | RHashtable _ -> pr "Hashtable"
9879    | RBufferOut _ -> pr "%s" string
9880   );
9881   pr ")"
9882
9883 and generate_bindtests () =
9884   generate_header CStyle LGPLv2;
9885
9886   pr "\
9887 #include <stdio.h>
9888 #include <stdlib.h>
9889 #include <inttypes.h>
9890 #include <string.h>
9891
9892 #include \"guestfs.h\"
9893 #include \"guestfs-internal.h\"
9894 #include \"guestfs-internal-actions.h\"
9895 #include \"guestfs_protocol.h\"
9896
9897 #define error guestfs_error
9898 #define safe_calloc guestfs_safe_calloc
9899 #define safe_malloc guestfs_safe_malloc
9900
9901 static void
9902 print_strings (char *const *argv)
9903 {
9904   int argc;
9905
9906   printf (\"[\");
9907   for (argc = 0; argv[argc] != NULL; ++argc) {
9908     if (argc > 0) printf (\", \");
9909     printf (\"\\\"%%s\\\"\", argv[argc]);
9910   }
9911   printf (\"]\\n\");
9912 }
9913
9914 /* The test0 function prints its parameters to stdout. */
9915 ";
9916
9917   let test0, tests =
9918     match test_functions with
9919     | [] -> assert false
9920     | test0 :: tests -> test0, tests in
9921
9922   let () =
9923     let (name, style, _, _, _, _, _) = test0 in
9924     generate_prototype ~extern:false ~semicolon:false ~newline:true
9925       ~handle:"g" ~prefix:"guestfs__" name style;
9926     pr "{\n";
9927     List.iter (
9928       function
9929       | Pathname n
9930       | Device n | Dev_or_Path n
9931       | String n
9932       | FileIn n
9933       | FileOut n -> pr "  printf (\"%%s\\n\", %s);\n" n
9934       | OptString n -> pr "  printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
9935       | StringList n | DeviceList n -> pr "  print_strings (%s);\n" n
9936       | Bool n -> pr "  printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
9937       | Int n -> pr "  printf (\"%%d\\n\", %s);\n" n
9938       | Int64 n -> pr "  printf (\"%%\" PRIi64 \"\\n\", %s);\n" n
9939     ) (snd style);
9940     pr "  /* Java changes stdout line buffering so we need this: */\n";
9941     pr "  fflush (stdout);\n";
9942     pr "  return 0;\n";
9943     pr "}\n";
9944     pr "\n" in
9945
9946   List.iter (
9947     fun (name, style, _, _, _, _, _) ->
9948       if String.sub name (String.length name - 3) 3 <> "err" then (
9949         pr "/* Test normal return. */\n";
9950         generate_prototype ~extern:false ~semicolon:false ~newline:true
9951           ~handle:"g" ~prefix:"guestfs__" name style;
9952         pr "{\n";
9953         (match fst style with
9954          | RErr ->
9955              pr "  return 0;\n"
9956          | RInt _ ->
9957              pr "  int r;\n";
9958              pr "  sscanf (val, \"%%d\", &r);\n";
9959              pr "  return r;\n"
9960          | RInt64 _ ->
9961              pr "  int64_t r;\n";
9962              pr "  sscanf (val, \"%%\" SCNi64, &r);\n";
9963              pr "  return r;\n"
9964          | RBool _ ->
9965              pr "  return STREQ (val, \"true\");\n"
9966          | RConstString _
9967          | RConstOptString _ ->
9968              (* Can't return the input string here.  Return a static
9969               * string so we ensure we get a segfault if the caller
9970               * tries to free it.
9971               *)
9972              pr "  return \"static string\";\n"
9973          | RString _ ->
9974              pr "  return strdup (val);\n"
9975          | RStringList _ ->
9976              pr "  char **strs;\n";
9977              pr "  int n, i;\n";
9978              pr "  sscanf (val, \"%%d\", &n);\n";
9979              pr "  strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
9980              pr "  for (i = 0; i < n; ++i) {\n";
9981              pr "    strs[i] = safe_malloc (g, 16);\n";
9982              pr "    snprintf (strs[i], 16, \"%%d\", i);\n";
9983              pr "  }\n";
9984              pr "  strs[n] = NULL;\n";
9985              pr "  return strs;\n"
9986          | RStruct (_, typ) ->
9987              pr "  struct guestfs_%s *r;\n" typ;
9988              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
9989              pr "  return r;\n"
9990          | RStructList (_, typ) ->
9991              pr "  struct guestfs_%s_list *r;\n" typ;
9992              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
9993              pr "  sscanf (val, \"%%d\", &r->len);\n";
9994              pr "  r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
9995              pr "  return r;\n"
9996          | RHashtable _ ->
9997              pr "  char **strs;\n";
9998              pr "  int n, i;\n";
9999              pr "  sscanf (val, \"%%d\", &n);\n";
10000              pr "  strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
10001              pr "  for (i = 0; i < n; ++i) {\n";
10002              pr "    strs[i*2] = safe_malloc (g, 16);\n";
10003              pr "    strs[i*2+1] = safe_malloc (g, 16);\n";
10004              pr "    snprintf (strs[i*2], 16, \"%%d\", i);\n";
10005              pr "    snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
10006              pr "  }\n";
10007              pr "  strs[n*2] = NULL;\n";
10008              pr "  return strs;\n"
10009          | RBufferOut _ ->
10010              pr "  return strdup (val);\n"
10011         );
10012         pr "}\n";
10013         pr "\n"
10014       ) else (
10015         pr "/* Test error return. */\n";
10016         generate_prototype ~extern:false ~semicolon:false ~newline:true
10017           ~handle:"g" ~prefix:"guestfs__" name style;
10018         pr "{\n";
10019         pr "  error (g, \"error\");\n";
10020         (match fst style with
10021          | RErr | RInt _ | RInt64 _ | RBool _ ->
10022              pr "  return -1;\n"
10023          | RConstString _ | RConstOptString _
10024          | RString _ | RStringList _ | RStruct _
10025          | RStructList _
10026          | RHashtable _
10027          | RBufferOut _ ->
10028              pr "  return NULL;\n"
10029         );
10030         pr "}\n";
10031         pr "\n"
10032       )
10033   ) tests
10034
10035 and generate_ocaml_bindtests () =
10036   generate_header OCamlStyle GPLv2;
10037
10038   pr "\
10039 let () =
10040   let g = Guestfs.create () in
10041 ";
10042
10043   let mkargs args =
10044     String.concat " " (
10045       List.map (
10046         function
10047         | CallString s -> "\"" ^ s ^ "\""
10048         | CallOptString None -> "None"
10049         | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
10050         | CallStringList xs ->
10051             "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
10052         | CallInt i when i >= 0 -> string_of_int i
10053         | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
10054         | CallInt64 i when i >= 0L -> Int64.to_string i ^ "L"
10055         | CallInt64 i (* when i < 0L *) -> "(" ^ Int64.to_string i ^ "L)"
10056         | CallBool b -> string_of_bool b
10057       ) args
10058     )
10059   in
10060
10061   generate_lang_bindtests (
10062     fun f args -> pr "  Guestfs.%s g %s;\n" f (mkargs args)
10063   );
10064
10065   pr "print_endline \"EOF\"\n"
10066
10067 and generate_perl_bindtests () =
10068   pr "#!/usr/bin/perl -w\n";
10069   generate_header HashStyle GPLv2;
10070
10071   pr "\
10072 use strict;
10073
10074 use Sys::Guestfs;
10075
10076 my $g = Sys::Guestfs->new ();
10077 ";
10078
10079   let mkargs args =
10080     String.concat ", " (
10081       List.map (
10082         function
10083         | CallString s -> "\"" ^ s ^ "\""
10084         | CallOptString None -> "undef"
10085         | CallOptString (Some s) -> sprintf "\"%s\"" s
10086         | CallStringList xs ->
10087             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10088         | CallInt i -> string_of_int i
10089         | CallInt64 i -> Int64.to_string i
10090         | CallBool b -> if b then "1" else "0"
10091       ) args
10092     )
10093   in
10094
10095   generate_lang_bindtests (
10096     fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
10097   );
10098
10099   pr "print \"EOF\\n\"\n"
10100
10101 and generate_python_bindtests () =
10102   generate_header HashStyle GPLv2;
10103
10104   pr "\
10105 import guestfs
10106
10107 g = guestfs.GuestFS ()
10108 ";
10109
10110   let mkargs args =
10111     String.concat ", " (
10112       List.map (
10113         function
10114         | CallString s -> "\"" ^ s ^ "\""
10115         | CallOptString None -> "None"
10116         | CallOptString (Some s) -> sprintf "\"%s\"" s
10117         | CallStringList xs ->
10118             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10119         | CallInt i -> string_of_int i
10120         | CallInt64 i -> Int64.to_string i
10121         | CallBool b -> if b then "1" else "0"
10122       ) args
10123     )
10124   in
10125
10126   generate_lang_bindtests (
10127     fun f args -> pr "g.%s (%s)\n" f (mkargs args)
10128   );
10129
10130   pr "print \"EOF\"\n"
10131
10132 and generate_ruby_bindtests () =
10133   generate_header HashStyle GPLv2;
10134
10135   pr "\
10136 require 'guestfs'
10137
10138 g = Guestfs::create()
10139 ";
10140
10141   let mkargs args =
10142     String.concat ", " (
10143       List.map (
10144         function
10145         | CallString s -> "\"" ^ s ^ "\""
10146         | CallOptString None -> "nil"
10147         | CallOptString (Some s) -> sprintf "\"%s\"" s
10148         | CallStringList xs ->
10149             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10150         | CallInt i -> string_of_int i
10151         | CallInt64 i -> Int64.to_string i
10152         | CallBool b -> string_of_bool b
10153       ) args
10154     )
10155   in
10156
10157   generate_lang_bindtests (
10158     fun f args -> pr "g.%s(%s)\n" f (mkargs args)
10159   );
10160
10161   pr "print \"EOF\\n\"\n"
10162
10163 and generate_java_bindtests () =
10164   generate_header CStyle GPLv2;
10165
10166   pr "\
10167 import com.redhat.et.libguestfs.*;
10168
10169 public class Bindtests {
10170     public static void main (String[] argv)
10171     {
10172         try {
10173             GuestFS g = new GuestFS ();
10174 ";
10175
10176   let mkargs args =
10177     String.concat ", " (
10178       List.map (
10179         function
10180         | CallString s -> "\"" ^ s ^ "\""
10181         | CallOptString None -> "null"
10182         | CallOptString (Some s) -> sprintf "\"%s\"" s
10183         | CallStringList xs ->
10184             "new String[]{" ^
10185               String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
10186         | CallInt i -> string_of_int i
10187         | CallInt64 i -> Int64.to_string i
10188         | CallBool b -> string_of_bool b
10189       ) args
10190     )
10191   in
10192
10193   generate_lang_bindtests (
10194     fun f args -> pr "            g.%s (%s);\n" f (mkargs args)
10195   );
10196
10197   pr "
10198             System.out.println (\"EOF\");
10199         }
10200         catch (Exception exn) {
10201             System.err.println (exn);
10202             System.exit (1);
10203         }
10204     }
10205 }
10206 "
10207
10208 and generate_haskell_bindtests () =
10209   generate_header HaskellStyle GPLv2;
10210
10211   pr "\
10212 module Bindtests where
10213 import qualified Guestfs
10214
10215 main = do
10216   g <- Guestfs.create
10217 ";
10218
10219   let mkargs args =
10220     String.concat " " (
10221       List.map (
10222         function
10223         | CallString s -> "\"" ^ s ^ "\""
10224         | CallOptString None -> "Nothing"
10225         | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
10226         | CallStringList xs ->
10227             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10228         | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
10229         | CallInt i -> string_of_int i
10230         | CallInt64 i when i < 0L -> "(" ^ Int64.to_string i ^ ")"
10231         | CallInt64 i -> Int64.to_string i
10232         | CallBool true -> "True"
10233         | CallBool false -> "False"
10234       ) args
10235     )
10236   in
10237
10238   generate_lang_bindtests (
10239     fun f args -> pr "  Guestfs.%s g %s\n" f (mkargs args)
10240   );
10241
10242   pr "  putStrLn \"EOF\"\n"
10243
10244 (* Language-independent bindings tests - we do it this way to
10245  * ensure there is parity in testing bindings across all languages.
10246  *)
10247 and generate_lang_bindtests call =
10248   call "test0" [CallString "abc"; CallOptString (Some "def");
10249                 CallStringList []; CallBool false;
10250                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10251   call "test0" [CallString "abc"; CallOptString None;
10252                 CallStringList []; CallBool false;
10253                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10254   call "test0" [CallString ""; CallOptString (Some "def");
10255                 CallStringList []; CallBool false;
10256                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10257   call "test0" [CallString ""; CallOptString (Some "");
10258                 CallStringList []; CallBool false;
10259                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10260   call "test0" [CallString "abc"; CallOptString (Some "def");
10261                 CallStringList ["1"]; CallBool false;
10262                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10263   call "test0" [CallString "abc"; CallOptString (Some "def");
10264                 CallStringList ["1"; "2"]; CallBool false;
10265                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10266   call "test0" [CallString "abc"; CallOptString (Some "def");
10267                 CallStringList ["1"]; CallBool true;
10268                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10269   call "test0" [CallString "abc"; CallOptString (Some "def");
10270                 CallStringList ["1"]; CallBool false;
10271                 CallInt (-1); CallInt64 (-1L); CallString "123"; CallString "456"];
10272   call "test0" [CallString "abc"; CallOptString (Some "def");
10273                 CallStringList ["1"]; CallBool false;
10274                 CallInt (-2); CallInt64 (-2L); CallString "123"; CallString "456"];
10275   call "test0" [CallString "abc"; CallOptString (Some "def");
10276                 CallStringList ["1"]; CallBool false;
10277                 CallInt 1; CallInt64 1L; CallString "123"; CallString "456"];
10278   call "test0" [CallString "abc"; CallOptString (Some "def");
10279                 CallStringList ["1"]; CallBool false;
10280                 CallInt 2; CallInt64 2L; CallString "123"; CallString "456"];
10281   call "test0" [CallString "abc"; CallOptString (Some "def");
10282                 CallStringList ["1"]; CallBool false;
10283                 CallInt 4095; CallInt64 4095L; CallString "123"; CallString "456"];
10284   call "test0" [CallString "abc"; CallOptString (Some "def");
10285                 CallStringList ["1"]; CallBool false;
10286                 CallInt 0; CallInt64 0L; CallString ""; CallString ""]
10287
10288 (* XXX Add here tests of the return and error functions. *)
10289
10290 (* This is used to generate the src/MAX_PROC_NR file which
10291  * contains the maximum procedure number, a surrogate for the
10292  * ABI version number.  See src/Makefile.am for the details.
10293  *)
10294 and generate_max_proc_nr () =
10295   let proc_nrs = List.map (
10296     fun (_, _, proc_nr, _, _, _, _) -> proc_nr
10297   ) daemon_functions in
10298
10299   let max_proc_nr = List.fold_left max 0 proc_nrs in
10300
10301   pr "%d\n" max_proc_nr
10302
10303 let output_to filename =
10304   let filename_new = filename ^ ".new" in
10305   chan := open_out filename_new;
10306   let close () =
10307     close_out !chan;
10308     chan := Pervasives.stdout;
10309
10310     (* Is the new file different from the current file? *)
10311     if Sys.file_exists filename && files_equal filename filename_new then
10312       unlink filename_new               (* same, so skip it *)
10313     else (
10314       (* different, overwrite old one *)
10315       (try chmod filename 0o644 with Unix_error _ -> ());
10316       rename filename_new filename;
10317       chmod filename 0o444;
10318       printf "written %s\n%!" filename;
10319     )
10320   in
10321   close
10322
10323 let perror msg = function
10324   | Unix_error (err, _, _) ->
10325       eprintf "%s: %s\n" msg (error_message err)
10326   | exn ->
10327       eprintf "%s: %s\n" msg (Printexc.to_string exn)
10328
10329 (* Main program. *)
10330 let () =
10331   let lock_fd =
10332     try openfile "HACKING" [O_RDWR] 0
10333     with
10334     | Unix_error (ENOENT, _, _) ->
10335         eprintf "\
10336 You are probably running this from the wrong directory.
10337 Run it from the top source directory using the command
10338   src/generator.ml
10339 ";
10340         exit 1
10341     | exn ->
10342         perror "open: HACKING" exn;
10343         exit 1 in
10344
10345   (* Acquire a lock so parallel builds won't try to run the generator
10346    * twice at the same time.  Subsequent builds will wait for the first
10347    * one to finish.  Note the lock is released implicitly when the
10348    * program exits.
10349    *)
10350   (try lockf lock_fd F_LOCK 1
10351    with exn ->
10352      perror "lock: HACKING" exn;
10353      exit 1);
10354
10355   check_functions ();
10356
10357   let close = output_to "src/guestfs_protocol.x" in
10358   generate_xdr ();
10359   close ();
10360
10361   let close = output_to "src/guestfs-structs.h" in
10362   generate_structs_h ();
10363   close ();
10364
10365   let close = output_to "src/guestfs-actions.h" in
10366   generate_actions_h ();
10367   close ();
10368
10369   let close = output_to "src/guestfs-internal-actions.h" in
10370   generate_internal_actions_h ();
10371   close ();
10372
10373   let close = output_to "src/guestfs-actions.c" in
10374   generate_client_actions ();
10375   close ();
10376
10377   let close = output_to "daemon/actions.h" in
10378   generate_daemon_actions_h ();
10379   close ();
10380
10381   let close = output_to "daemon/stubs.c" in
10382   generate_daemon_actions ();
10383   close ();
10384
10385   let close = output_to "daemon/names.c" in
10386   generate_daemon_names ();
10387   close ();
10388
10389   let close = output_to "daemon/optgroups.c" in
10390   generate_daemon_optgroups_c ();
10391   close ();
10392
10393   let close = output_to "daemon/optgroups.h" in
10394   generate_daemon_optgroups_h ();
10395   close ();
10396
10397   let close = output_to "capitests/tests.c" in
10398   generate_tests ();
10399   close ();
10400
10401   let close = output_to "src/guestfs-bindtests.c" in
10402   generate_bindtests ();
10403   close ();
10404
10405   let close = output_to "fish/cmds.c" in
10406   generate_fish_cmds ();
10407   close ();
10408
10409   let close = output_to "fish/completion.c" in
10410   generate_fish_completion ();
10411   close ();
10412
10413   let close = output_to "guestfs-structs.pod" in
10414   generate_structs_pod ();
10415   close ();
10416
10417   let close = output_to "guestfs-actions.pod" in
10418   generate_actions_pod ();
10419   close ();
10420
10421   let close = output_to "guestfs-availability.pod" in
10422   generate_availability_pod ();
10423   close ();
10424
10425   let close = output_to "guestfish-actions.pod" in
10426   generate_fish_actions_pod ();
10427   close ();
10428
10429   let close = output_to "ocaml/guestfs.mli" in
10430   generate_ocaml_mli ();
10431   close ();
10432
10433   let close = output_to "ocaml/guestfs.ml" in
10434   generate_ocaml_ml ();
10435   close ();
10436
10437   let close = output_to "ocaml/guestfs_c_actions.c" in
10438   generate_ocaml_c ();
10439   close ();
10440
10441   let close = output_to "ocaml/bindtests.ml" in
10442   generate_ocaml_bindtests ();
10443   close ();
10444
10445   let close = output_to "perl/Guestfs.xs" in
10446   generate_perl_xs ();
10447   close ();
10448
10449   let close = output_to "perl/lib/Sys/Guestfs.pm" in
10450   generate_perl_pm ();
10451   close ();
10452
10453   let close = output_to "perl/bindtests.pl" in
10454   generate_perl_bindtests ();
10455   close ();
10456
10457   let close = output_to "python/guestfs-py.c" in
10458   generate_python_c ();
10459   close ();
10460
10461   let close = output_to "python/guestfs.py" in
10462   generate_python_py ();
10463   close ();
10464
10465   let close = output_to "python/bindtests.py" in
10466   generate_python_bindtests ();
10467   close ();
10468
10469   let close = output_to "ruby/ext/guestfs/_guestfs.c" in
10470   generate_ruby_c ();
10471   close ();
10472
10473   let close = output_to "ruby/bindtests.rb" in
10474   generate_ruby_bindtests ();
10475   close ();
10476
10477   let close = output_to "java/com/redhat/et/libguestfs/GuestFS.java" in
10478   generate_java_java ();
10479   close ();
10480
10481   List.iter (
10482     fun (typ, jtyp) ->
10483       let cols = cols_of_struct typ in
10484       let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
10485       let close = output_to filename in
10486       generate_java_struct jtyp cols;
10487       close ();
10488   ) java_structs;
10489
10490   let close = output_to "java/Makefile.inc" in
10491   generate_java_makefile_inc ();
10492   close ();
10493
10494   let close = output_to "java/com_redhat_et_libguestfs_GuestFS.c" in
10495   generate_java_c ();
10496   close ();
10497
10498   let close = output_to "java/Bindtests.java" in
10499   generate_java_bindtests ();
10500   close ();
10501
10502   let close = output_to "haskell/Guestfs.hs" in
10503   generate_haskell_hs ();
10504   close ();
10505
10506   let close = output_to "haskell/Bindtests.hs" in
10507   generate_haskell_bindtests ();
10508   close ();
10509
10510   let close = output_to "src/MAX_PROC_NR" in
10511   generate_max_proc_nr ();
10512   close ();
10513
10514   (* Always generate this file last, and unconditionally.  It's used
10515    * by the Makefile to know when we must re-run the generator.
10516    *)
10517   let chan = open_out "src/stamp-generator" in
10518   fprintf chan "1\n";
10519   close_out chan