Just use plain lists for argument representation.
[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.  To add a new action there are only two
22  * files you need to change, this one to describe the interface, and
23  * daemon/<somefile>.c to write the implementation.
24  *
25  * After editing this file, run it (./src/generator.ml) to regenerate
26  * all the output files.
27  *
28  * IMPORTANT: This script should not print any warnings.  If it prints
29  * warnings, you should treat them as errors.
30  * [Need to add -warn-error to ocaml command line]
31  *)
32
33 #load "unix.cma";;
34
35 open Printf
36
37 type style = ret * args
38 and ret =
39     (* "Err" as a return value means an int used as a simple error
40      * indication, ie. 0 or -1.
41      *)
42   | Err
43     (* "RInt" as a return value means an int which is -1 for error
44      * or any value >= 0 on success.
45      *)
46   | RInt of string
47     (* "RBool" is a bool return value which can be true/false or
48      * -1 for error.
49      *)
50   | RBool of string
51     (* "RConstString" is a string that refers to a constant value.
52      * Try to avoid using this.  In particular you cannot use this
53      * for values returned from the daemon, because there is no
54      * thread-safe way to return them in the C API.
55      *)
56   | RConstString of string
57     (* "RString" and "RStringList" are caller-frees. *)
58   | RString of string
59   | RStringList of string
60     (* Some limited tuples are possible: *)
61   | RIntBool of string * string
62     (* LVM PVs, VGs and LVs. *)
63   | RPVList of string
64   | RVGList of string
65   | RLVList of string
66 and args = argt list    (* Function parameters, guestfs handle is implicit. *)
67 and argt =
68   | String of string    (* const char *name, cannot be NULL *)
69   | OptString of string (* const char *name, may be NULL *)
70   | Bool of string      (* boolean *)
71   | Int of string       (* int (smallish ints, signed, <= 31 bits) *)
72
73 type flags =
74   | ProtocolLimitWarning  (* display warning about protocol size limits *)
75   | FishAlias of string   (* provide an alias for this cmd in guestfish *)
76   | FishAction of string  (* call this function in guestfish *)
77   | NotInFish             (* do not export via guestfish *)
78
79 (* Note about long descriptions: When referring to another
80  * action, use the format C<guestfs_other> (ie. the full name of
81  * the C function).  This will be replaced as appropriate in other
82  * language bindings.
83  *
84  * Apart from that, long descriptions are just perldoc paragraphs.
85  *)
86
87 let non_daemon_functions = [
88   ("launch", (Err, []), -1, [FishAlias "run"; FishAction "launch"],
89    "launch the qemu subprocess",
90    "\
91 Internally libguestfs is implemented by running a virtual machine
92 using L<qemu(1)>.
93
94 You should call this after configuring the handle
95 (eg. adding drives) but before performing any actions.");
96
97   ("wait_ready", (Err, []), -1, [NotInFish],
98    "wait until the qemu subprocess launches",
99    "\
100 Internally libguestfs is implemented by running a virtual machine
101 using L<qemu(1)>.
102
103 You should call this after C<guestfs_launch> to wait for the launch
104 to complete.");
105
106   ("kill_subprocess", (Err, []), -1, [],
107    "kill the qemu subprocess",
108    "\
109 This kills the qemu subprocess.  You should never need to call this.");
110
111   ("add_drive", (Err, [String "filename"]), -1, [FishAlias "add"],
112    "add an image to examine or modify",
113    "\
114 This function adds a virtual machine disk image C<filename> to the
115 guest.  The first time you call this function, the disk appears as IDE
116 disk 0 (C</dev/sda>) in the guest, the second time as C</dev/sdb>, and
117 so on.
118
119 You don't necessarily need to be root when using libguestfs.  However
120 you obviously do need sufficient permissions to access the filename
121 for whatever operations you want to perform (ie. read access if you
122 just want to read the image or write access if you want to modify the
123 image).
124
125 This is equivalent to the qemu parameter C<-drive file=filename>.");
126
127   ("add_cdrom", (Err, [String "filename"]), -1, [FishAlias "cdrom"],
128    "add a CD-ROM disk image to examine",
129    "\
130 This function adds a virtual CD-ROM disk image to the guest.
131
132 This is equivalent to the qemu parameter C<-cdrom filename>.");
133
134   ("config", (Err, [String "qemuparam"; OptString "qemuvalue"]), -1, [],
135    "add qemu parameters",
136    "\
137 This can be used to add arbitrary qemu command line parameters
138 of the form C<-param value>.  Actually it's not quite arbitrary - we
139 prevent you from setting some parameters which would interfere with
140 parameters that we use.
141
142 The first character of C<param> string must be a C<-> (dash).
143
144 C<value> can be NULL.");
145
146   ("set_path", (Err, [String "path"]), -1, [FishAlias "path"],
147    "set the search path",
148    "\
149 Set the path that libguestfs searches for kernel and initrd.img.
150
151 The default is C<$libdir/guestfs> unless overridden by setting
152 C<LIBGUESTFS_PATH> environment variable.
153
154 The string C<path> is stashed in the libguestfs handle, so the caller
155 must make sure it remains valid for the lifetime of the handle.
156
157 Setting C<path> to C<NULL> restores the default path.");
158
159   ("get_path", (RConstString "path", []), -1, [],
160    "get the search path",
161    "\
162 Return the current search path.
163
164 This is always non-NULL.  If it wasn't set already, then this will
165 return the default path.");
166
167   ("set_autosync", (Err, [Bool "autosync"]), -1, [FishAlias "autosync"],
168    "set autosync mode",
169    "\
170 If C<autosync> is true, this enables autosync.  Libguestfs will make a
171 best effort attempt to run C<guestfs_sync> when the handle is closed
172 (also if the program exits without closing handles).");
173
174   ("get_autosync", (RBool "autosync", []), -1, [],
175    "get autosync mode",
176    "\
177 Get the autosync flag.");
178
179   ("set_verbose", (Err, [Bool "verbose"]), -1, [FishAlias "verbose"],
180    "set verbose mode",
181    "\
182 If C<verbose> is true, this turns on verbose messages (to C<stderr>).
183
184 Verbose messages are disabled unless the environment variable
185 C<LIBGUESTFS_DEBUG> is defined and set to C<1>.");
186
187   ("get_verbose", (RBool "verbose", []), -1, [],
188    "get verbose mode",
189    "\
190 This returns the verbose messages flag.")
191 ]
192
193 let daemon_functions = [
194   ("mount", (Err, [String "device"; String "mountpoint"]), 1, [],
195    "mount a guest disk at a position in the filesystem",
196    "\
197 Mount a guest disk at a position in the filesystem.  Block devices
198 are named C</dev/sda>, C</dev/sdb> and so on, as they were added to
199 the guest.  If those block devices contain partitions, they will have
200 the usual names (eg. C</dev/sda1>).  Also LVM C</dev/VG/LV>-style
201 names can be used.
202
203 The rules are the same as for L<mount(2)>:  A filesystem must
204 first be mounted on C</> before others can be mounted.  Other
205 filesystems can only be mounted on directories which already
206 exist.
207
208 The mounted filesystem is writable, if we have sufficient permissions
209 on the underlying device.
210
211 The filesystem options C<sync> and C<noatime> are set with this
212 call, in order to improve reliability.");
213
214   ("sync", (Err, []), 2, [],
215    "sync disks, writes are flushed through to the disk image",
216    "\
217 This syncs the disk, so that any writes are flushed through to the
218 underlying disk image.
219
220 You should always call this if you have modified a disk image, before
221 closing the handle.");
222
223   ("touch", (Err, [String "path"]), 3, [],
224    "update file timestamps or create a new file",
225    "\
226 Touch acts like the L<touch(1)> command.  It can be used to
227 update the timestamps on a file, or, if the file does not exist,
228 to create a new zero-length file.");
229
230   ("cat", (RString "content", [String "path"]), 4, [ProtocolLimitWarning],
231    "list the contents of a file",
232    "\
233 Return the contents of the file named C<path>.
234
235 Note that this function cannot correctly handle binary files
236 (specifically, files containing C<\\0> character which is treated
237 as end of string).  For those you need to use the C<guestfs_read_file>
238 function which has a more complex interface.");
239
240   ("ll", (RString "listing", [String "directory"]), 5, [],
241    "list the files in a directory (long format)",
242    "\
243 List the files in C<directory> (relative to the root directory,
244 there is no cwd) in the format of 'ls -la'.
245
246 This command is mostly useful for interactive sessions.  It
247 is I<not> intended that you try to parse the output string.");
248
249   ("ls", (RStringList "listing", [String "directory"]), 6, [],
250    "list the files in a directory",
251    "\
252 List the files in C<directory> (relative to the root directory,
253 there is no cwd).  The '.' and '..' entries are not returned, but
254 hidden files are shown.
255
256 This command is mostly useful for interactive sessions.  Programs
257 should probably use C<guestfs_readdir> instead.");
258
259   ("list_devices", (RStringList "devices", []), 7, [],
260    "list the block devices",
261    "\
262 List all the block devices.
263
264 The full block device names are returned, eg. C</dev/sda>");
265
266   ("list_partitions", (RStringList "partitions", []), 8, [],
267    "list the partitions",
268    "\
269 List all the partitions detected on all block devices.
270
271 The full partition device names are returned, eg. C</dev/sda1>
272
273 This does not return logical volumes.  For that you will need to
274 call C<guestfs_lvs>.");
275
276   ("pvs", (RStringList "physvols", []), 9, [],
277    "list the LVM physical volumes (PVs)",
278    "\
279 List all the physical volumes detected.  This is the equivalent
280 of the L<pvs(8)> command.
281
282 This returns a list of just the device names that contain
283 PVs (eg. C</dev/sda2>).
284
285 See also C<guestfs_pvs_full>.");
286
287   ("vgs", (RStringList "volgroups", []), 10, [],
288    "list the LVM volume groups (VGs)",
289    "\
290 List all the volumes groups detected.  This is the equivalent
291 of the L<vgs(8)> command.
292
293 This returns a list of just the volume group names that were
294 detected (eg. C<VolGroup00>).
295
296 See also C<guestfs_vgs_full>.");
297
298   ("lvs", (RStringList "logvols", []), 11, [],
299    "list the LVM logical volumes (LVs)",
300    "\
301 List all the logical volumes detected.  This is the equivalent
302 of the L<lvs(8)> command.
303
304 This returns a list of the logical volume device names
305 (eg. C</dev/VolGroup00/LogVol00>).
306
307 See also C<guestfs_lvs_full>.");
308
309   ("pvs_full", (RPVList "physvols", []), 12, [],
310    "list the LVM physical volumes (PVs)",
311    "\
312 List all the physical volumes detected.  This is the equivalent
313 of the L<pvs(8)> command.  The \"full\" version includes all fields.");
314
315   ("vgs_full", (RVGList "volgroups", []), 13, [],
316    "list the LVM volume groups (VGs)",
317    "\
318 List all the volumes groups detected.  This is the equivalent
319 of the L<vgs(8)> command.  The \"full\" version includes all fields.");
320
321   ("lvs_full", (RLVList "logvols", []), 14, [],
322    "list the LVM logical volumes (LVs)",
323    "\
324 List all the logical volumes detected.  This is the equivalent
325 of the L<lvs(8)> command.  The \"full\" version includes all fields.");
326
327   ("read_lines", (RStringList "lines", [String "path"]), 15, [],
328    "read file as lines",
329    "\
330 Return the contents of the file named C<path>.
331
332 The file contents are returned as a list of lines.  Trailing
333 C<LF> and C<CRLF> character sequences are I<not> returned.
334
335 Note that this function cannot correctly handle binary files
336 (specifically, files containing C<\\0> character which is treated
337 as end of line).  For those you need to use the C<guestfs_read_file>
338 function which has a more complex interface.");
339
340   ("aug_init", (Err, [String "root"; Int "flags"]), 16, [],
341    "create a new Augeas handle",
342    "\
343 Create a new Augeas handle for editing configuration files.
344 If there was any previous Augeas handle associated with this
345 guestfs session, then it is closed.
346
347 You must call this before using any other C<guestfs_aug_*>
348 commands.
349
350 C<root> is the filesystem root.  C<root> must not be NULL,
351 use C</> instead.
352
353 The flags are the same as the flags defined in
354 E<lt>augeas.hE<gt>, the logical I<or> of the following
355 integers:
356
357 =over 4
358
359 =item C<AUG_SAVE_BACKUP> = 1
360
361 Keep the original file with a C<.augsave> extension.
362
363 =item C<AUG_SAVE_NEWFILE> = 2
364
365 Save changes into a file with extension C<.augnew>, and
366 do not overwrite original.  Overrides C<AUG_SAVE_BACKUP>.
367
368 =item C<AUG_TYPE_CHECK> = 4
369
370 Typecheck lenses (can be expensive).
371
372 =item C<AUG_NO_STDINC> = 8
373
374 Do not use standard load path for modules.
375
376 =item C<AUG_SAVE_NOOP> = 16
377
378 Make save a no-op, just record what would have been changed.
379
380 =item C<AUG_NO_LOAD> = 32
381
382 Do not load the tree in C<guestfs_aug_init>.
383
384 =back
385
386 To close the handle, you can call C<guestfs_aug_close>.
387
388 To find out more about Augeas, see L<http://augeas.net/>.");
389
390   ("aug_close", (Err, []), 26, [],
391    "close the current Augeas handle",
392    "\
393 Close the current Augeas handle and free up any resources
394 used by it.  After calling this, you have to call
395 C<guestfs_aug_init> again before you can use any other
396 Augeas functions.");
397
398   ("aug_defvar", (RInt "nrnodes", [String "name"; OptString "expr"]), 17, [],
399    "define an Augeas variable",
400    "\
401 Defines an Augeas variable C<name> whose value is the result
402 of evaluating C<expr>.  If C<expr> is NULL, then C<name> is
403 undefined.
404
405 On success this returns the number of nodes in C<expr>, or
406 C<0> if C<expr> evaluates to something which is not a nodeset.");
407
408   ("aug_defnode", (RIntBool ("nrnodes", "created"), [String "name"; String "expr"; String "val"]), 18, [],
409    "define an Augeas node",
410    "\
411 Defines a variable C<name> whose value is the result of
412 evaluating C<expr>.
413
414 If C<expr> evaluates to an empty nodeset, a node is created,
415 equivalent to calling C<guestfs_aug_set> C<expr>, C<value>.
416 C<name> will be the nodeset containing that single node.
417
418 On success this returns a pair containing the
419 number of nodes in the nodeset, and a boolean flag
420 if a node was created.");
421
422   ("aug_get", (RString "val", [String "path"]), 19, [],
423    "look up the value of an Augeas path",
424    "\
425 Look up the value associated with C<path>.  If C<path>
426 matches exactly one node, the C<value> is returned.");
427
428   ("aug_set", (Err, [String "path"; String "val"]), 20, [],
429    "set Augeas path to value",
430    "\
431 Set the value associated with C<path> to C<value>.");
432
433   ("aug_insert", (Err, [String "path"; String "label"; Bool "before"]), 21, [],
434    "insert a sibling Augeas node",
435    "\
436 Create a new sibling C<label> for C<path>, inserting it into
437 the tree before or after C<path> (depending on the boolean
438 flag C<before>).
439
440 C<path> must match exactly one existing node in the tree, and
441 C<label> must be a label, ie. not contain C</>, C<*> or end
442 with a bracketed index C<[N]>.");
443
444   ("aug_rm", (RInt "nrnodes", [String "path"]), 22, [],
445    "remove an Augeas path",
446    "\
447 Remove C<path> and all of its children.
448
449 On success this returns the number of entries which were removed.");
450
451   ("aug_mv", (Err, [String "src"; String "dest"]), 23, [],
452    "move Augeas node",
453    "\
454 Move the node C<src> to C<dest>.  C<src> must match exactly
455 one node.  C<dest> is overwritten if it exists.");
456
457   ("aug_match", (RStringList "matches", [String "path"]), 24, [],
458    "return Augeas nodes which match path",
459    "\
460 Returns a list of paths which match the path expression C<path>.
461 The returned paths are sufficiently qualified so that they match
462 exactly one node in the current tree.");
463
464   ("aug_save", (Err, []), 25, [],
465    "write all pending Augeas changes to disk",
466    "\
467 This writes all pending changes to disk.
468
469 The flags which were passed to C<guestfs_aug_init> affect exactly
470 how files are saved.");
471
472   ("aug_load", (Err, []), 27, [],
473    "load files into the tree",
474    "\
475 Load files into the tree.
476
477 See C<aug_load> in the Augeas documentation for the full gory
478 details.");
479
480   ("aug_ls", (RStringList "matches", [String "path"]), 28, [],
481    "list Augeas nodes under a path",
482    "\
483 This is just a shortcut for listing C<guestfs_aug_match>
484 C<path/*> and sorting the resulting nodes into alphabetical order.");
485 ]
486
487 let all_functions = non_daemon_functions @ daemon_functions
488
489 (* In some places we want the functions to be displayed sorted
490  * alphabetically, so this is useful:
491  *)
492 let all_functions_sorted =
493   List.sort (fun (n1,_,_,_,_,_) (n2,_,_,_,_,_) -> compare n1 n2) all_functions
494
495 (* Column names and types from LVM PVs/VGs/LVs. *)
496 let pv_cols = [
497   "pv_name", `String;
498   "pv_uuid", `UUID;
499   "pv_fmt", `String;
500   "pv_size", `Bytes;
501   "dev_size", `Bytes;
502   "pv_free", `Bytes;
503   "pv_used", `Bytes;
504   "pv_attr", `String (* XXX *);
505   "pv_pe_count", `Int;
506   "pv_pe_alloc_count", `Int;
507   "pv_tags", `String;
508   "pe_start", `Bytes;
509   "pv_mda_count", `Int;
510   "pv_mda_free", `Bytes;
511 (* Not in Fedora 10:
512   "pv_mda_size", `Bytes;
513 *)
514 ]
515 let vg_cols = [
516   "vg_name", `String;
517   "vg_uuid", `UUID;
518   "vg_fmt", `String;
519   "vg_attr", `String (* XXX *);
520   "vg_size", `Bytes;
521   "vg_free", `Bytes;
522   "vg_sysid", `String;
523   "vg_extent_size", `Bytes;
524   "vg_extent_count", `Int;
525   "vg_free_count", `Int;
526   "max_lv", `Int;
527   "max_pv", `Int;
528   "pv_count", `Int;
529   "lv_count", `Int;
530   "snap_count", `Int;
531   "vg_seqno", `Int;
532   "vg_tags", `String;
533   "vg_mda_count", `Int;
534   "vg_mda_free", `Bytes;
535 (* Not in Fedora 10:
536   "vg_mda_size", `Bytes;
537 *)
538 ]
539 let lv_cols = [
540   "lv_name", `String;
541   "lv_uuid", `UUID;
542   "lv_attr", `String (* XXX *);
543   "lv_major", `Int;
544   "lv_minor", `Int;
545   "lv_kernel_major", `Int;
546   "lv_kernel_minor", `Int;
547   "lv_size", `Bytes;
548   "seg_count", `Int;
549   "origin", `String;
550   "snap_percent", `OptPercent;
551   "copy_percent", `OptPercent;
552   "move_pv", `String;
553   "lv_tags", `String;
554   "mirror_log", `String;
555   "modules", `String;
556 ]
557
558 (* Useful functions.
559  * Note we don't want to use any external OCaml libraries which
560  * makes this a bit harder than it should be.
561  *)
562 let failwithf fs = ksprintf failwith fs
563
564 let replace_char s c1 c2 =
565   let s2 = String.copy s in
566   let r = ref false in
567   for i = 0 to String.length s2 - 1 do
568     if String.unsafe_get s2 i = c1 then (
569       String.unsafe_set s2 i c2;
570       r := true
571     )
572   done;
573   if not !r then s else s2
574
575 let rec find s sub =
576   let len = String.length s in
577   let sublen = String.length sub in
578   let rec loop i =
579     if i <= len-sublen then (
580       let rec loop2 j =
581         if j < sublen then (
582           if s.[i+j] = sub.[j] then loop2 (j+1)
583           else -1
584         ) else
585           i (* found *)
586       in
587       let r = loop2 0 in
588       if r = -1 then loop (i+1) else r
589     ) else
590       -1 (* not found *)
591   in
592   loop 0
593
594 let rec replace_str s s1 s2 =
595   let len = String.length s in
596   let sublen = String.length s1 in
597   let i = find s s1 in
598   if i = -1 then s
599   else (
600     let s' = String.sub s 0 i in
601     let s'' = String.sub s (i+sublen) (len-i-sublen) in
602     s' ^ s2 ^ replace_str s'' s1 s2
603   )
604
605 let rec find_map f = function
606   | [] -> raise Not_found
607   | x :: xs ->
608       match f x with
609       | Some y -> y
610       | None -> find_map f xs
611
612 let iteri f xs =
613   let rec loop i = function
614     | [] -> ()
615     | x :: xs -> f i x; loop (i+1) xs
616   in
617   loop 0 xs
618
619 (* 'pr' prints to the current output file. *)
620 let chan = ref stdout
621 let pr fs = ksprintf (output_string !chan) fs
622
623 let name_of_argt = function String n | OptString n | Bool n | Int n -> n
624
625 (* Check function names etc. for consistency. *)
626 let check_functions () =
627   List.iter (
628     fun (name, _, _, _, _, longdesc) ->
629       if String.contains name '-' then
630         failwithf "function name '%s' should not contain '-', use '_' instead."
631           name;
632       if longdesc.[String.length longdesc-1] = '\n' then
633         failwithf "long description of %s should not end with \\n." name
634   ) all_functions;
635
636   List.iter (
637     fun (name, _, proc_nr, _, _, _) ->
638       if proc_nr <= 0 then
639         failwithf "daemon function %s should have proc_nr > 0" name
640   ) daemon_functions;
641
642   List.iter (
643     fun (name, _, proc_nr, _, _, _) ->
644       if proc_nr <> -1 then
645         failwithf "non-daemon function %s should have proc_nr -1" name
646   ) non_daemon_functions;
647
648   let proc_nrs =
649     List.map (fun (name, _, proc_nr, _, _, _) -> name, proc_nr)
650       daemon_functions in
651   let proc_nrs =
652     List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
653   let rec loop = function
654     | [] -> ()
655     | [_] -> ()
656     | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
657         loop rest
658     | (name1,nr1) :: (name2,nr2) :: _ ->
659         failwithf "'%s' and '%s' have conflicting procedure numbers (%d, %d)"
660           name1 name2 nr1 nr2
661   in
662   loop proc_nrs
663
664 type comment_style = CStyle | HashStyle | OCamlStyle
665 type license = GPLv2 | LGPLv2
666
667 (* Generate a header block in a number of standard styles. *)
668 let rec generate_header comment license =
669   let c = match comment with
670     | CStyle ->     pr "/* "; " *"
671     | HashStyle ->  pr "# ";  "#"
672     | OCamlStyle -> pr "(* "; " *" in
673   pr "libguestfs generated file\n";
674   pr "%s WARNING: THIS FILE IS GENERATED BY 'src/generator.ml'.\n" c;
675   pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
676   pr "%s\n" c;
677   pr "%s Copyright (C) 2009 Red Hat Inc.\n" c;
678   pr "%s\n" c;
679   (match license with
680    | GPLv2 ->
681        pr "%s This program is free software; you can redistribute it and/or modify\n" c;
682        pr "%s it under the terms of the GNU General Public License as published by\n" c;
683        pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
684        pr "%s (at your option) any later version.\n" c;
685        pr "%s\n" c;
686        pr "%s This program is distributed in the hope that it will be useful,\n" c;
687        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
688        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n" c;
689        pr "%s GNU General Public License for more details.\n" c;
690        pr "%s\n" c;
691        pr "%s You should have received a copy of the GNU General Public License along\n" c;
692        pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
693        pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
694
695    | LGPLv2 ->
696        pr "%s This library is free software; you can redistribute it and/or\n" c;
697        pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
698        pr "%s License as published by the Free Software Foundation; either\n" c;
699        pr "%s version 2 of the License, or (at your option) any later version.\n" c;
700        pr "%s\n" c;
701        pr "%s This library is distributed in the hope that it will be useful,\n" c;
702        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
703        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n" c;
704        pr "%s Lesser General Public License for more details.\n" c;
705        pr "%s\n" c;
706        pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
707        pr "%s License along with this library; if not, write to the Free Software\n" c;
708        pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
709   );
710   (match comment with
711    | CStyle -> pr " */\n"
712    | HashStyle -> ()
713    | OCamlStyle -> pr " *)\n"
714   );
715   pr "\n"
716
717 (* Generate the pod documentation for the C API. *)
718 and generate_actions_pod () =
719   List.iter (
720     fun (shortname, style, _, flags, _, longdesc) ->
721       let name = "guestfs_" ^ shortname in
722       pr "=head2 %s\n\n" name;
723       pr " ";
724       generate_prototype ~extern:false ~handle:"handle" name style;
725       pr "\n\n";
726       pr "%s\n\n" longdesc;
727       (match fst style with
728        | Err ->
729            pr "This function returns 0 on success or -1 on error.\n\n"
730        | RInt _ ->
731            pr "On error this function returns -1.\n\n"
732        | RBool _ ->
733            pr "This function returns a C truth value on success or -1 on error.\n\n"
734        | RConstString _ ->
735            pr "This function returns a string or NULL on error.
736 The string is owned by the guest handle and must I<not> be freed.\n\n"
737        | RString _ ->
738            pr "This function returns a string or NULL on error.
739 I<The caller must free the returned string after use>.\n\n"
740        | RStringList _ ->
741            pr "This function returns a NULL-terminated array of strings
742 (like L<environ(3)>), or NULL if there was an error.
743 I<The caller must free the strings and the array after use>.\n\n"
744        | RIntBool _ ->
745            pr "This function returns a C<struct guestfs_int_bool *>.
746 I<The caller must call C<guestfs_free_int_bool> after use.>.\n\n"
747        | RPVList _ ->
748            pr "This function returns a C<struct guestfs_lvm_pv_list *>.
749 I<The caller must call C<guestfs_free_lvm_pv_list> after use.>.\n\n"
750        | RVGList _ ->
751            pr "This function returns a C<struct guestfs_lvm_vg_list *>.
752 I<The caller must call C<guestfs_free_lvm_vg_list> after use.>.\n\n"
753        | RLVList _ ->
754            pr "This function returns a C<struct guestfs_lvm_lv_list *>.
755 I<The caller must call C<guestfs_free_lvm_lv_list> after use.>.\n\n"
756       );
757       if List.mem ProtocolLimitWarning flags then
758         pr "Because of the message protocol, there is a transfer limit 
759 of somewhere between 2MB and 4MB.  To transfer large files you should use
760 FTP.\n\n";
761   ) all_functions_sorted
762
763 and generate_structs_pod () =
764   (* LVM structs documentation. *)
765   List.iter (
766     fun (typ, cols) ->
767       pr "=head2 guestfs_lvm_%s\n" typ;
768       pr "\n";
769       pr " struct guestfs_lvm_%s {\n" typ;
770       List.iter (
771         function
772         | name, `String -> pr "  char *%s;\n" name
773         | name, `UUID ->
774             pr "  /* The next field is NOT nul-terminated, be careful when printing it: */\n";
775             pr "  char %s[32];\n" name
776         | name, `Bytes -> pr "  uint64_t %s;\n" name
777         | name, `Int -> pr "  int64_t %s;\n" name
778         | name, `OptPercent ->
779             pr "  /* The next field is [0..100] or -1 meaning 'not present': */\n";
780             pr "  float %s;\n" name
781       ) cols;
782       pr " \n";
783       pr " struct guestfs_lvm_%s_list {\n" typ;
784       pr "   uint32_t len; /* Number of elements in list. */\n";
785       pr "   struct guestfs_lvm_%s *val; /* Elements. */\n" typ;
786       pr " };\n";
787       pr " \n";
788       pr " void guestfs_free_lvm_%s_list (struct guestfs_free_lvm_%s_list *);\n"
789         typ typ;
790       pr "\n"
791   ) ["pv", pv_cols; "vg", vg_cols; "lv", lv_cols]
792
793 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
794  * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.  We
795  * have to use an underscore instead of a dash because otherwise
796  * rpcgen generates incorrect code.
797  *
798  * This header is NOT exported to clients, but see also generate_structs_h.
799  *)
800 and generate_xdr () =
801   generate_header CStyle LGPLv2;
802
803   (* This has to be defined to get around a limitation in Sun's rpcgen. *)
804   pr "typedef string str<>;\n";
805   pr "\n";
806
807   (* LVM internal structures. *)
808   List.iter (
809     function
810     | typ, cols ->
811         pr "struct guestfs_lvm_int_%s {\n" typ;
812         List.iter (function
813                    | name, `String -> pr "  string %s<>;\n" name
814                    | name, `UUID -> pr "  opaque %s[32];\n" name
815                    | name, `Bytes -> pr "  hyper %s;\n" name
816                    | name, `Int -> pr "  hyper %s;\n" name
817                    | name, `OptPercent -> pr "  float %s;\n" name
818                   ) cols;
819         pr "};\n";
820         pr "\n";
821         pr "typedef struct guestfs_lvm_int_%s guestfs_lvm_int_%s_list<>;\n" typ typ;
822         pr "\n";
823   ) ["pv", pv_cols; "vg", vg_cols; "lv", lv_cols];
824
825   List.iter (
826     fun(shortname, style, _, _, _, _) ->
827       let name = "guestfs_" ^ shortname in
828
829       (match snd style with
830        | [] -> ()
831        | args ->
832            pr "struct %s_args {\n" name;
833            List.iter (
834              function
835              | String n -> pr "  string %s<>;\n" n
836              | OptString n -> pr "  str *%s;\n" n
837              | Bool n -> pr "  bool %s;\n" n
838              | Int n -> pr "  int %s;\n" n
839            ) args;
840            pr "};\n\n"
841       );
842       (match fst style with
843        | Err -> ()
844        | RInt n ->
845            pr "struct %s_ret {\n" name;
846            pr "  int %s;\n" n;
847            pr "};\n\n"
848        | RBool n ->
849            pr "struct %s_ret {\n" name;
850            pr "  bool %s;\n" n;
851            pr "};\n\n"
852        | RConstString _ ->
853            failwithf "RConstString cannot be returned from a daemon function"
854        | RString n ->
855            pr "struct %s_ret {\n" name;
856            pr "  string %s<>;\n" n;
857            pr "};\n\n"
858        | RStringList n ->
859            pr "struct %s_ret {\n" name;
860            pr "  str %s<>;\n" n;
861            pr "};\n\n"
862        | RIntBool (n,m) ->
863            pr "struct %s_ret {\n" name;
864            pr "  int %s;\n" n;
865            pr "  bool %s;\n" m;
866            pr "};\n\n"
867        | RPVList n ->
868            pr "struct %s_ret {\n" name;
869            pr "  guestfs_lvm_int_pv_list %s;\n" n;
870            pr "};\n\n"
871        | RVGList n ->
872            pr "struct %s_ret {\n" name;
873            pr "  guestfs_lvm_int_vg_list %s;\n" n;
874            pr "};\n\n"
875        | RLVList n ->
876            pr "struct %s_ret {\n" name;
877            pr "  guestfs_lvm_int_lv_list %s;\n" n;
878            pr "};\n\n"
879       );
880   ) daemon_functions;
881
882   (* Table of procedure numbers. *)
883   pr "enum guestfs_procedure {\n";
884   List.iter (
885     fun (shortname, _, proc_nr, _, _, _) ->
886       pr "  GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
887   ) daemon_functions;
888   pr "  GUESTFS_PROC_dummy\n"; (* so we don't have a "hanging comma" *)
889   pr "};\n";
890   pr "\n";
891
892   (* Having to choose a maximum message size is annoying for several
893    * reasons (it limits what we can do in the API), but it (a) makes
894    * the protocol a lot simpler, and (b) provides a bound on the size
895    * of the daemon which operates in limited memory space.  For large
896    * file transfers you should use FTP.
897    *)
898   pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
899   pr "\n";
900
901   (* Message header, etc. *)
902   pr "\
903 const GUESTFS_PROGRAM = 0x2000F5F5;
904 const GUESTFS_PROTOCOL_VERSION = 1;
905
906 enum guestfs_message_direction {
907   GUESTFS_DIRECTION_CALL = 0,        /* client -> daemon */
908   GUESTFS_DIRECTION_REPLY = 1        /* daemon -> client */
909 };
910
911 enum guestfs_message_status {
912   GUESTFS_STATUS_OK = 0,
913   GUESTFS_STATUS_ERROR = 1
914 };
915
916 const GUESTFS_ERROR_LEN = 256;
917
918 struct guestfs_message_error {
919   string error<GUESTFS_ERROR_LEN>;   /* error message */
920 };
921
922 struct guestfs_message_header {
923   unsigned prog;                     /* GUESTFS_PROGRAM */
924   unsigned vers;                     /* GUESTFS_PROTOCOL_VERSION */
925   guestfs_procedure proc;            /* GUESTFS_PROC_x */
926   guestfs_message_direction direction;
927   unsigned serial;                   /* message serial number */
928   guestfs_message_status status;
929 };
930 "
931
932 (* Generate the guestfs-structs.h file. *)
933 and generate_structs_h () =
934   generate_header CStyle LGPLv2;
935
936   (* This is a public exported header file containing various
937    * structures.  The structures are carefully written to have
938    * exactly the same in-memory format as the XDR structures that
939    * we use on the wire to the daemon.  The reason for creating
940    * copies of these structures here is just so we don't have to
941    * export the whole of guestfs_protocol.h (which includes much
942    * unrelated and XDR-dependent stuff that we don't want to be
943    * public, or required by clients).
944    *
945    * To reiterate, we will pass these structures to and from the
946    * client with a simple assignment or memcpy, so the format
947    * must be identical to what rpcgen / the RFC defines.
948    *)
949
950   (* guestfs_int_bool structure. *)
951   pr "struct guestfs_int_bool {\n";
952   pr "  int32_t i;\n";
953   pr "  int32_t b;\n";
954   pr "};\n";
955   pr "\n";
956
957   (* LVM public structures. *)
958   List.iter (
959     function
960     | typ, cols ->
961         pr "struct guestfs_lvm_%s {\n" typ;
962         List.iter (
963           function
964           | name, `String -> pr "  char *%s;\n" name
965           | name, `UUID -> pr "  char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
966           | name, `Bytes -> pr "  uint64_t %s;\n" name
967           | name, `Int -> pr "  int64_t %s;\n" name
968           | name, `OptPercent -> pr "  float %s; /* [0..100] or -1 */\n" name
969         ) cols;
970         pr "};\n";
971         pr "\n";
972         pr "struct guestfs_lvm_%s_list {\n" typ;
973         pr "  uint32_t len;\n";
974         pr "  struct guestfs_lvm_%s *val;\n" typ;
975         pr "};\n";
976         pr "\n"
977   ) ["pv", pv_cols; "vg", vg_cols; "lv", lv_cols]
978
979 (* Generate the guestfs-actions.h file. *)
980 and generate_actions_h () =
981   generate_header CStyle LGPLv2;
982   List.iter (
983     fun (shortname, style, _, _, _, _) ->
984       let name = "guestfs_" ^ shortname in
985       generate_prototype ~single_line:true ~newline:true ~handle:"handle"
986         name style
987   ) all_functions
988
989 (* Generate the client-side dispatch stubs. *)
990 and generate_client_actions () =
991   generate_header CStyle LGPLv2;
992
993   (* Client-side stubs for each function. *)
994   List.iter (
995     fun (shortname, style, _, _, _, _) ->
996       let name = "guestfs_" ^ shortname in
997
998       (* Generate the return value struct. *)
999       pr "struct %s_rv {\n" shortname;
1000       pr "  int cb_done;  /* flag to indicate callback was called */\n";
1001       pr "  struct guestfs_message_header hdr;\n";
1002       pr "  struct guestfs_message_error err;\n";
1003       (match fst style with
1004        | Err -> ()
1005        | RConstString _ ->
1006            failwithf "RConstString cannot be returned from a daemon function"
1007        | RInt _
1008        | RBool _ | RString _ | RStringList _
1009        | RIntBool _
1010        | RPVList _ | RVGList _ | RLVList _ ->
1011            pr "  struct %s_ret ret;\n" name
1012       );
1013       pr "};\n\n";
1014
1015       (* Generate the callback function. *)
1016       pr "static void %s_cb (guestfs_h *g, void *data, XDR *xdr)\n" shortname;
1017       pr "{\n";
1018       pr "  struct %s_rv *rv = (struct %s_rv *) data;\n" shortname shortname;
1019       pr "\n";
1020       pr "  if (!xdr_guestfs_message_header (xdr, &rv->hdr)) {\n";
1021       pr "    error (g, \"%s: failed to parse reply header\");\n" name;
1022       pr "    return;\n";
1023       pr "  }\n";
1024       pr "  if (rv->hdr.status == GUESTFS_STATUS_ERROR) {\n";
1025       pr "    if (!xdr_guestfs_message_error (xdr, &rv->err)) {\n";
1026       pr "      error (g, \"%s: failed to parse reply error\");\n" name;
1027       pr "      return;\n";
1028       pr "    }\n";
1029       pr "    goto done;\n";
1030       pr "  }\n";
1031
1032       (match fst style with
1033        | Err -> ()
1034        | RConstString _ ->
1035            failwithf "RConstString cannot be returned from a daemon function"
1036        | RInt _
1037        | RBool _ | RString _ | RStringList _
1038        | RIntBool _
1039        | RPVList _ | RVGList _ | RLVList _ ->
1040             pr "  if (!xdr_%s_ret (xdr, &rv->ret)) {\n" name;
1041             pr "    error (g, \"%s: failed to parse reply\");\n" name;
1042             pr "    return;\n";
1043             pr "  }\n";
1044       );
1045
1046       pr " done:\n";
1047       pr "  rv->cb_done = 1;\n";
1048       pr "  main_loop.main_loop_quit (g);\n";
1049       pr "}\n\n";
1050
1051       (* Generate the action stub. *)
1052       generate_prototype ~extern:false ~semicolon:false ~newline:true
1053         ~handle:"g" name style;
1054
1055       let error_code =
1056         match fst style with
1057         | Err | RInt _ | RBool _ -> "-1"
1058         | RConstString _ ->
1059             failwithf "RConstString cannot be returned from a daemon function"
1060         | RString _ | RStringList _ | RIntBool _
1061         | RPVList _ | RVGList _ | RLVList _ ->
1062             "NULL" in
1063
1064       pr "{\n";
1065
1066       (match snd style with
1067        | [] -> ()
1068        | _ -> pr "  struct %s_args args;\n" name
1069       );
1070
1071       pr "  struct %s_rv rv;\n" shortname;
1072       pr "  int serial;\n";
1073       pr "\n";
1074       pr "  if (g->state != READY) {\n";
1075       pr "    error (g, \"%s called from the wrong state, %%d != READY\",\n"
1076         name;
1077       pr "      g->state);\n";
1078       pr "    return %s;\n" error_code;
1079       pr "  }\n";
1080       pr "\n";
1081       pr "  memset (&rv, 0, sizeof rv);\n";
1082       pr "\n";
1083
1084       (match snd style with
1085        | [] ->
1086            pr "  serial = dispatch (g, GUESTFS_PROC_%s, NULL, NULL);\n"
1087              (String.uppercase shortname)
1088        | args ->
1089            List.iter (
1090              function
1091              | String n ->
1092                  pr "  args.%s = (char *) %s;\n" n n
1093              | OptString n ->
1094                  pr "  args.%s = %s ? (char **) &%s : NULL;\n" n n n
1095              | Bool n ->
1096                  pr "  args.%s = %s;\n" n n
1097              | Int n ->
1098                  pr "  args.%s = %s;\n" n n
1099            ) args;
1100            pr "  serial = dispatch (g, GUESTFS_PROC_%s,\n"
1101              (String.uppercase shortname);
1102            pr "                     (xdrproc_t) xdr_%s_args, (char *) &args);\n"
1103              name;
1104       );
1105       pr "  if (serial == -1)\n";
1106       pr "    return %s;\n" error_code;
1107       pr "\n";
1108
1109       pr "  rv.cb_done = 0;\n";
1110       pr "  g->reply_cb_internal = %s_cb;\n" shortname;
1111       pr "  g->reply_cb_internal_data = &rv;\n";
1112       pr "  main_loop.main_loop_run (g);\n";
1113       pr "  g->reply_cb_internal = NULL;\n";
1114       pr "  g->reply_cb_internal_data = NULL;\n";
1115       pr "  if (!rv.cb_done) {\n";
1116       pr "    error (g, \"%s failed, see earlier error messages\");\n" name;
1117       pr "    return %s;\n" error_code;
1118       pr "  }\n";
1119       pr "\n";
1120
1121       pr "  if (check_reply_header (g, &rv.hdr, GUESTFS_PROC_%s, serial) == -1)\n"
1122         (String.uppercase shortname);
1123       pr "    return %s;\n" error_code;
1124       pr "\n";
1125
1126       pr "  if (rv.hdr.status == GUESTFS_STATUS_ERROR) {\n";
1127       pr "    error (g, \"%%s\", rv.err.error);\n";
1128       pr "    return %s;\n" error_code;
1129       pr "  }\n";
1130       pr "\n";
1131
1132       (match fst style with
1133        | Err -> pr "  return 0;\n"
1134        | RInt n
1135        | RBool n -> pr "  return rv.ret.%s;\n" n
1136        | RConstString _ ->
1137            failwithf "RConstString cannot be returned from a daemon function"
1138        | RString n ->
1139            pr "  return rv.ret.%s; /* caller will free */\n" n
1140        | RStringList n ->
1141            pr "  /* caller will free this, but we need to add a NULL entry */\n";
1142            pr "  rv.ret.%s.%s_val =" n n;
1143            pr "    safe_realloc (g, rv.ret.%s.%s_val,\n" n n;
1144            pr "                  sizeof (char *) * (rv.ret.%s.%s_len + 1));\n"
1145              n n;
1146            pr "  rv.ret.%s.%s_val[rv.ret.%s.%s_len] = NULL;\n" n n n n;
1147            pr "  return rv.ret.%s.%s_val;\n" n n
1148        | RIntBool _ ->
1149            pr "  /* caller with free this */\n";
1150            pr "  return safe_memdup (g, &rv.ret, sizeof (rv.ret));\n"
1151        | RPVList n ->
1152            pr "  /* caller will free this */\n";
1153            pr "  return safe_memdup (g, &rv.ret.%s, sizeof (rv.ret.%s));\n" n n
1154        | RVGList n ->
1155            pr "  /* caller will free this */\n";
1156            pr "  return safe_memdup (g, &rv.ret.%s, sizeof (rv.ret.%s));\n" n n
1157        | RLVList n ->
1158            pr "  /* caller will free this */\n";
1159            pr "  return safe_memdup (g, &rv.ret.%s, sizeof (rv.ret.%s));\n" n n
1160       );
1161
1162       pr "}\n\n"
1163   ) daemon_functions
1164
1165 (* Generate daemon/actions.h. *)
1166 and generate_daemon_actions_h () =
1167   generate_header CStyle GPLv2;
1168
1169   pr "#include \"../src/guestfs_protocol.h\"\n";
1170   pr "\n";
1171
1172   List.iter (
1173     fun (name, style, _, _, _, _) ->
1174         generate_prototype
1175           ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
1176           name style;
1177   ) daemon_functions
1178
1179 (* Generate the server-side stubs. *)
1180 and generate_daemon_actions () =
1181   generate_header CStyle GPLv2;
1182
1183   pr "#define _GNU_SOURCE // for strchrnul\n";
1184   pr "\n";
1185   pr "#include <stdio.h>\n";
1186   pr "#include <stdlib.h>\n";
1187   pr "#include <string.h>\n";
1188   pr "#include <inttypes.h>\n";
1189   pr "#include <ctype.h>\n";
1190   pr "#include <rpc/types.h>\n";
1191   pr "#include <rpc/xdr.h>\n";
1192   pr "\n";
1193   pr "#include \"daemon.h\"\n";
1194   pr "#include \"../src/guestfs_protocol.h\"\n";
1195   pr "#include \"actions.h\"\n";
1196   pr "\n";
1197
1198   List.iter (
1199     fun (name, style, _, _, _, _) ->
1200       (* Generate server-side stubs. *)
1201       pr "static void %s_stub (XDR *xdr_in)\n" name;
1202       pr "{\n";
1203       let error_code =
1204         match fst style with
1205         | Err | RInt _ -> pr "  int r;\n"; "-1"
1206         | RBool _ -> pr "  int r;\n"; "-1"
1207         | RConstString _ ->
1208             failwithf "RConstString cannot be returned from a daemon function"
1209         | RString _ -> pr "  char *r;\n"; "NULL"
1210         | RStringList _ -> pr "  char **r;\n"; "NULL"
1211         | RIntBool _ -> pr "  guestfs_%s_ret *r;\n" name; "NULL"
1212         | RPVList _ -> pr "  guestfs_lvm_int_pv_list *r;\n"; "NULL"
1213         | RVGList _ -> pr "  guestfs_lvm_int_vg_list *r;\n"; "NULL"
1214         | RLVList _ -> pr "  guestfs_lvm_int_lv_list *r;\n"; "NULL" in
1215
1216       (match snd style with
1217        | [] -> ()
1218        | args ->
1219            pr "  struct guestfs_%s_args args;\n" name;
1220            List.iter (
1221              function
1222              | String n
1223              | OptString n -> pr "  const char *%s;\n" n
1224              | Bool n -> pr "  int %s;\n" n
1225              | Int n -> pr "  int %s;\n" n
1226            ) args
1227       );
1228       pr "\n";
1229
1230       (match snd style with
1231        | [] -> ()
1232        | args ->
1233            pr "  memset (&args, 0, sizeof args);\n";
1234            pr "\n";
1235            pr "  if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
1236            pr "    reply_with_error (\"%%s: daemon failed to decode procedure arguments\", \"%s\");\n" name;
1237            pr "    return;\n";
1238            pr "  }\n";
1239            List.iter (
1240              function
1241              | String n -> pr "  %s = args.%s;\n" n n
1242              | OptString n -> pr "  %s = args.%s ? *args.%s : NULL;\n" n n n
1243              | Bool n -> pr "  %s = args.%s;\n" n n
1244              | Int n -> pr "  %s = args.%s;\n" n n
1245            ) args;
1246            pr "\n"
1247       );
1248
1249       pr "  r = do_%s " name;
1250       generate_call_args style;
1251       pr ";\n";
1252
1253       pr "  if (r == %s)\n" error_code;
1254       pr "    /* do_%s has already called reply_with_error, so just return */\n" name;
1255       pr "    return;\n";
1256       pr "\n";
1257
1258       (match fst style with
1259        | Err -> pr "  reply (NULL, NULL);\n"
1260        | RInt n ->
1261            pr "  struct guestfs_%s_ret ret;\n" name;
1262            pr "  ret.%s = r;\n" n;
1263            pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n" name
1264        | RBool n ->
1265            pr "  struct guestfs_%s_ret ret;\n" name;
1266            pr "  ret.%s = r;\n" n;
1267            pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n" name
1268        | RConstString _ ->
1269            failwithf "RConstString cannot be returned from a daemon function"
1270        | RString n ->
1271            pr "  struct guestfs_%s_ret ret;\n" name;
1272            pr "  ret.%s = r;\n" n;
1273            pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n" name;
1274            pr "  free (r);\n"
1275        | RStringList n ->
1276            pr "  struct guestfs_%s_ret ret;\n" name;
1277            pr "  ret.%s.%s_len = count_strings (r);\n" n n;
1278            pr "  ret.%s.%s_val = r;\n" n n;
1279            pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n" name;
1280            pr "  free_strings (r);\n"
1281        | RIntBool _ ->
1282            pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) r);\n" name;
1283            pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) r);\n" name
1284        | RPVList n ->
1285            pr "  struct guestfs_%s_ret ret;\n" name;
1286            pr "  ret.%s = *r;\n" n;
1287            pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n" name;
1288            pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n" name
1289        | RVGList n ->
1290            pr "  struct guestfs_%s_ret ret;\n" name;
1291            pr "  ret.%s = *r;\n" n;
1292            pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n" name;
1293            pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n" name
1294        | RLVList n ->
1295            pr "  struct guestfs_%s_ret ret;\n" name;
1296            pr "  ret.%s = *r;\n" n;
1297            pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n" name;
1298            pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n" name
1299       );
1300
1301       pr "}\n\n";
1302   ) daemon_functions;
1303
1304   (* Dispatch function. *)
1305   pr "void dispatch_incoming_message (XDR *xdr_in)\n";
1306   pr "{\n";
1307   pr "  switch (proc_nr) {\n";
1308
1309   List.iter (
1310     fun (name, style, _, _, _, _) ->
1311         pr "    case GUESTFS_PROC_%s:\n" (String.uppercase name);
1312         pr "      %s_stub (xdr_in);\n" name;
1313         pr "      break;\n"
1314   ) daemon_functions;
1315
1316   pr "    default:\n";
1317   pr "      reply_with_error (\"dispatch_incoming_message: unknown procedure number %%d\", proc_nr);\n";
1318   pr "  }\n";
1319   pr "}\n";
1320   pr "\n";
1321
1322   (* LVM columns and tokenization functions. *)
1323   (* XXX This generates crap code.  We should rethink how we
1324    * do this parsing.
1325    *)
1326   List.iter (
1327     function
1328     | typ, cols ->
1329         pr "static const char *lvm_%s_cols = \"%s\";\n"
1330           typ (String.concat "," (List.map fst cols));
1331         pr "\n";
1332
1333         pr "static int lvm_tokenize_%s (char *str, struct guestfs_lvm_int_%s *r)\n" typ typ;
1334         pr "{\n";
1335         pr "  char *tok, *p, *next;\n";
1336         pr "  int i, j;\n";
1337         pr "\n";
1338         (*
1339         pr "  fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
1340         pr "\n";
1341         *)
1342         pr "  if (!str) {\n";
1343         pr "    fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
1344         pr "    return -1;\n";
1345         pr "  }\n";
1346         pr "  if (!*str || isspace (*str)) {\n";
1347         pr "    fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
1348         pr "    return -1;\n";
1349         pr "  }\n";
1350         pr "  tok = str;\n";
1351         List.iter (
1352           fun (name, coltype) ->
1353             pr "  if (!tok) {\n";
1354             pr "    fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
1355             pr "    return -1;\n";
1356             pr "  }\n";
1357             pr "  p = strchrnul (tok, ',');\n";
1358             pr "  if (*p) next = p+1; else next = NULL;\n";
1359             pr "  *p = '\\0';\n";
1360             (match coltype with
1361              | `String ->
1362                  pr "  r->%s = strdup (tok);\n" name;
1363                  pr "  if (r->%s == NULL) {\n" name;
1364                  pr "    perror (\"strdup\");\n";
1365                  pr "    return -1;\n";
1366                  pr "  }\n"
1367              | `UUID ->
1368                  pr "  for (i = j = 0; i < 32; ++j) {\n";
1369                  pr "    if (tok[j] == '\\0') {\n";
1370                  pr "      fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
1371                  pr "      return -1;\n";
1372                  pr "    } else if (tok[j] != '-')\n";
1373                  pr "      r->%s[i++] = tok[j];\n" name;
1374                  pr "  }\n";
1375              | `Bytes ->
1376                  pr "  if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
1377                  pr "    fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
1378                  pr "    return -1;\n";
1379                  pr "  }\n";
1380              | `Int ->
1381                  pr "  if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
1382                  pr "    fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
1383                  pr "    return -1;\n";
1384                  pr "  }\n";
1385              | `OptPercent ->
1386                  pr "  if (tok[0] == '\\0')\n";
1387                  pr "    r->%s = -1;\n" name;
1388                  pr "  else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
1389                  pr "    fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
1390                  pr "    return -1;\n";
1391                  pr "  }\n";
1392             );
1393             pr "  tok = next;\n";
1394         ) cols;
1395
1396         pr "  if (tok != NULL) {\n";
1397         pr "    fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
1398         pr "    return -1;\n";
1399         pr "  }\n";
1400         pr "  return 0;\n";
1401         pr "}\n";
1402         pr "\n";
1403
1404         pr "guestfs_lvm_int_%s_list *\n" typ;
1405         pr "parse_command_line_%ss (void)\n" typ;
1406         pr "{\n";
1407         pr "  char *out, *err;\n";
1408         pr "  char *p, *pend;\n";
1409         pr "  int r, i;\n";
1410         pr "  guestfs_lvm_int_%s_list *ret;\n" typ;
1411         pr "  void *newp;\n";
1412         pr "\n";
1413         pr "  ret = malloc (sizeof *ret);\n";
1414         pr "  if (!ret) {\n";
1415         pr "    reply_with_perror (\"malloc\");\n";
1416         pr "    return NULL;\n";
1417         pr "  }\n";
1418         pr "\n";
1419         pr "  ret->guestfs_lvm_int_%s_list_len = 0;\n" typ;
1420         pr "  ret->guestfs_lvm_int_%s_list_val = NULL;\n" typ;
1421         pr "\n";
1422         pr "  r = command (&out, &err,\n";
1423         pr "           \"/sbin/lvm\", \"%ss\",\n" typ;
1424         pr "           \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
1425         pr "           \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
1426         pr "  if (r == -1) {\n";
1427         pr "    reply_with_error (\"%%s\", err);\n";
1428         pr "    free (out);\n";
1429         pr "    free (err);\n";
1430         pr "    return NULL;\n";
1431         pr "  }\n";
1432         pr "\n";
1433         pr "  free (err);\n";
1434         pr "\n";
1435         pr "  /* Tokenize each line of the output. */\n";
1436         pr "  p = out;\n";
1437         pr "  i = 0;\n";
1438         pr "  while (p) {\n";
1439         pr "    pend = strchr (p, '\\n');       /* Get the next line of output. */\n";
1440         pr "    if (pend) {\n";
1441         pr "      *pend = '\\0';\n";
1442         pr "      pend++;\n";
1443         pr "    }\n";
1444         pr "\n";
1445         pr "    while (*p && isspace (*p))      /* Skip any leading whitespace. */\n";
1446         pr "      p++;\n";
1447         pr "\n";
1448         pr "    if (!*p) {                      /* Empty line?  Skip it. */\n";
1449         pr "      p = pend;\n";
1450         pr "      continue;\n";
1451         pr "    }\n";
1452         pr "\n";
1453         pr "    /* Allocate some space to store this next entry. */\n";
1454         pr "    newp = realloc (ret->guestfs_lvm_int_%s_list_val,\n" typ;
1455         pr "                sizeof (guestfs_lvm_int_%s) * (i+1));\n" typ;
1456         pr "    if (newp == NULL) {\n";
1457         pr "      reply_with_perror (\"realloc\");\n";
1458         pr "      free (ret->guestfs_lvm_int_%s_list_val);\n" typ;
1459         pr "      free (ret);\n";
1460         pr "      free (out);\n";
1461         pr "      return NULL;\n";
1462         pr "    }\n";
1463         pr "    ret->guestfs_lvm_int_%s_list_val = newp;\n" typ;
1464         pr "\n";
1465         pr "    /* Tokenize the next entry. */\n";
1466         pr "    r = lvm_tokenize_%s (p, &ret->guestfs_lvm_int_%s_list_val[i]);\n" typ typ;
1467         pr "    if (r == -1) {\n";
1468         pr "      reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
1469         pr "      free (ret->guestfs_lvm_int_%s_list_val);\n" typ;
1470         pr "      free (ret);\n";
1471         pr "      free (out);\n";
1472         pr "      return NULL;\n";
1473         pr "    }\n";
1474         pr "\n";
1475         pr "    ++i;\n";
1476         pr "    p = pend;\n";
1477         pr "  }\n";
1478         pr "\n";
1479         pr "  ret->guestfs_lvm_int_%s_list_len = i;\n" typ;
1480         pr "\n";
1481         pr "  free (out);\n";
1482         pr "  return ret;\n";
1483         pr "}\n"
1484
1485   ) ["pv", pv_cols; "vg", vg_cols; "lv", lv_cols]
1486
1487 (* Generate a lot of different functions for guestfish. *)
1488 and generate_fish_cmds () =
1489   generate_header CStyle GPLv2;
1490
1491   let all_functions =
1492     List.filter (
1493       fun (_, _, _, flags, _, _) -> not (List.mem NotInFish flags)
1494     ) all_functions in
1495   let all_functions_sorted =
1496     List.filter (
1497       fun (_, _, _, flags, _, _) -> not (List.mem NotInFish flags)
1498     ) all_functions_sorted in
1499
1500   pr "#include <stdio.h>\n";
1501   pr "#include <stdlib.h>\n";
1502   pr "#include <string.h>\n";
1503   pr "#include <inttypes.h>\n";
1504   pr "\n";
1505   pr "#include <guestfs.h>\n";
1506   pr "#include \"fish.h\"\n";
1507   pr "\n";
1508
1509   (* list_commands function, which implements guestfish -h *)
1510   pr "void list_commands (void)\n";
1511   pr "{\n";
1512   pr "  printf (\"    %%-16s     %%s\\n\", \"Command\", \"Description\");\n";
1513   pr "  list_builtin_commands ();\n";
1514   List.iter (
1515     fun (name, _, _, flags, shortdesc, _) ->
1516       let name = replace_char name '_' '-' in
1517       pr "  printf (\"%%-20s %%s\\n\", \"%s\", \"%s\");\n"
1518         name shortdesc
1519   ) all_functions_sorted;
1520   pr "  printf (\"    Use -h <cmd> / help <cmd> to show detailed help for a command.\\n\");\n";
1521   pr "}\n";
1522   pr "\n";
1523
1524   (* display_command function, which implements guestfish -h cmd *)
1525   pr "void display_command (const char *cmd)\n";
1526   pr "{\n";
1527   List.iter (
1528     fun (name, style, _, flags, shortdesc, longdesc) ->
1529       let name2 = replace_char name '_' '-' in
1530       let alias =
1531         try find_map (function FishAlias n -> Some n | _ -> None) flags
1532         with Not_found -> name in
1533       let longdesc = replace_str longdesc "C<guestfs_" "C<" in
1534       let synopsis =
1535         match snd style with
1536         | [] -> name2
1537         | args ->
1538             sprintf "%s <%s>"
1539               name2 (String.concat "> <" (List.map name_of_argt args)) in
1540
1541       let warnings =
1542         if List.mem ProtocolLimitWarning flags then
1543           "\n\nBecause of the message protocol, there is a transfer limit 
1544 of somewhere between 2MB and 4MB.  To transfer large files you should use
1545 FTP."
1546         else "" in
1547
1548       let describe_alias =
1549         if name <> alias then
1550           sprintf "\n\nYou can use '%s' as an alias for this command." alias
1551         else "" in
1552
1553       pr "  if (";
1554       pr "strcasecmp (cmd, \"%s\") == 0" name;
1555       if name <> name2 then
1556         pr " || strcasecmp (cmd, \"%s\") == 0" name2;
1557       if name <> alias then
1558         pr " || strcasecmp (cmd, \"%s\") == 0" alias;
1559       pr ")\n";
1560       pr "    pod2text (\"%s - %s\", %S);\n"
1561         name2 shortdesc
1562         (" " ^ synopsis ^ "\n\n" ^ longdesc ^ warnings ^ describe_alias);
1563       pr "  else\n"
1564   ) all_functions;
1565   pr "    display_builtin_command (cmd);\n";
1566   pr "}\n";
1567   pr "\n";
1568
1569   (* print_{pv,vg,lv}_list functions *)
1570   List.iter (
1571     function
1572     | typ, cols ->
1573         pr "static void print_%s (struct guestfs_lvm_%s *%s)\n" typ typ typ;
1574         pr "{\n";
1575         pr "  int i;\n";
1576         pr "\n";
1577         List.iter (
1578           function
1579           | name, `String ->
1580               pr "  printf (\"%s: %%s\\n\", %s->%s);\n" name typ name
1581           | name, `UUID ->
1582               pr "  printf (\"%s: \");\n" name;
1583               pr "  for (i = 0; i < 32; ++i)\n";
1584               pr "    printf (\"%%c\", %s->%s[i]);\n" typ name;
1585               pr "  printf (\"\\n\");\n"
1586           | name, `Bytes ->
1587               pr "  printf (\"%s: %%\" PRIu64 \"\\n\", %s->%s);\n" name typ name
1588           | name, `Int ->
1589               pr "  printf (\"%s: %%\" PRIi64 \"\\n\", %s->%s);\n" name typ name
1590           | name, `OptPercent ->
1591               pr "  if (%s->%s >= 0) printf (\"%s: %%g %%%%\\n\", %s->%s);\n"
1592                 typ name name typ name;
1593               pr "  else printf (\"%s: \\n\");\n" name
1594         ) cols;
1595         pr "}\n";
1596         pr "\n";
1597         pr "static void print_%s_list (struct guestfs_lvm_%s_list *%ss)\n"
1598           typ typ typ;
1599         pr "{\n";
1600         pr "  int i;\n";
1601         pr "\n";
1602         pr "  for (i = 0; i < %ss->len; ++i)\n" typ;
1603         pr "    print_%s (&%ss->val[i]);\n" typ typ;
1604         pr "}\n";
1605         pr "\n";
1606   ) ["pv", pv_cols; "vg", vg_cols; "lv", lv_cols];
1607
1608   (* run_<action> actions *)
1609   List.iter (
1610     fun (name, style, _, flags, _, _) ->
1611       pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
1612       pr "{\n";
1613       (match fst style with
1614        | Err
1615        | RInt _
1616        | RBool _ -> pr "  int r;\n"
1617        | RConstString _ -> pr "  const char *r;\n"
1618        | RString _ -> pr "  char *r;\n"
1619        | RStringList _ -> pr "  char **r;\n"
1620        | RIntBool _ -> pr "  struct guestfs_int_bool *r;\n"
1621        | RPVList _ -> pr "  struct guestfs_lvm_pv_list *r;\n"
1622        | RVGList _ -> pr "  struct guestfs_lvm_vg_list *r;\n"
1623        | RLVList _ -> pr "  struct guestfs_lvm_lv_list *r;\n"
1624       );
1625       List.iter (
1626         function
1627         | String n -> pr "  const char *%s;\n" n
1628         | OptString n -> pr "  const char *%s;\n" n
1629         | Bool n -> pr "  int %s;\n" n
1630         | Int n -> pr "  int %s;\n" n
1631       ) (snd style);
1632
1633       (* Check and convert parameters. *)
1634       let argc_expected = List.length (snd style) in
1635       pr "  if (argc != %d) {\n" argc_expected;
1636       pr "    fprintf (stderr, \"%%s should have %d parameter(s)\\n\", cmd);\n"
1637         argc_expected;
1638       pr "    fprintf (stderr, \"type 'help %%s' for help on %%s\\n\", cmd, cmd);\n";
1639       pr "    return -1;\n";
1640       pr "  }\n";
1641       iteri (
1642         fun i ->
1643           function
1644           | String name -> pr "  %s = argv[%d];\n" name i
1645           | OptString name ->
1646               pr "  %s = strcmp (argv[%d], \"\") != 0 ? argv[%d] : NULL;\n"
1647                 name i i
1648           | Bool name ->
1649               pr "  %s = is_true (argv[%d]) ? 1 : 0;\n" name i
1650           | Int name ->
1651               pr "  %s = atoi (argv[%d]);\n" name i
1652       ) (snd style);
1653
1654       (* Call C API function. *)
1655       let fn =
1656         try find_map (function FishAction n -> Some n | _ -> None) flags
1657         with Not_found -> sprintf "guestfs_%s" name in
1658       pr "  r = %s " fn;
1659       generate_call_args ~handle:"g" style;
1660       pr ";\n";
1661
1662       (* Check return value for errors and display command results. *)
1663       (match fst style with
1664        | Err -> pr "  return r;\n"
1665        | RInt _ ->
1666            pr "  if (r == -1) return -1;\n";
1667            pr "  if (r) printf (\"%%d\\n\", r);\n";
1668            pr "  return 0;\n"
1669        | RBool _ ->
1670            pr "  if (r == -1) return -1;\n";
1671            pr "  if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
1672            pr "  return 0;\n"
1673        | RConstString _ ->
1674            pr "  if (r == NULL) return -1;\n";
1675            pr "  printf (\"%%s\\n\", r);\n";
1676            pr "  return 0;\n"
1677        | RString _ ->
1678            pr "  if (r == NULL) return -1;\n";
1679            pr "  printf (\"%%s\\n\", r);\n";
1680            pr "  free (r);\n";
1681            pr "  return 0;\n"
1682        | RStringList _ ->
1683            pr "  if (r == NULL) return -1;\n";
1684            pr "  print_strings (r);\n";
1685            pr "  free_strings (r);\n";
1686            pr "  return 0;\n"
1687        | RIntBool _ ->
1688            pr "  if (r == NULL) return -1;\n";
1689            pr "  printf (\"%%d, %%s\\n\", r->i,\n";
1690            pr "    r->b ? \"true\" : \"false\");\n";
1691            pr "  guestfs_free_int_bool (r);\n";
1692            pr "  return 0;\n"
1693        | RPVList _ ->
1694            pr "  if (r == NULL) return -1;\n";
1695            pr "  print_pv_list (r);\n";
1696            pr "  guestfs_free_lvm_pv_list (r);\n";
1697            pr "  return 0;\n"
1698        | RVGList _ ->
1699            pr "  if (r == NULL) return -1;\n";
1700            pr "  print_vg_list (r);\n";
1701            pr "  guestfs_free_lvm_vg_list (r);\n";
1702            pr "  return 0;\n"
1703        | RLVList _ ->
1704            pr "  if (r == NULL) return -1;\n";
1705            pr "  print_lv_list (r);\n";
1706            pr "  guestfs_free_lvm_lv_list (r);\n";
1707            pr "  return 0;\n"
1708       );
1709       pr "}\n";
1710       pr "\n"
1711   ) all_functions;
1712
1713   (* run_action function *)
1714   pr "int run_action (const char *cmd, int argc, char *argv[])\n";
1715   pr "{\n";
1716   List.iter (
1717     fun (name, _, _, flags, _, _) ->
1718       let name2 = replace_char name '_' '-' in
1719       let alias =
1720         try find_map (function FishAlias n -> Some n | _ -> None) flags
1721         with Not_found -> name in
1722       pr "  if (";
1723       pr "strcasecmp (cmd, \"%s\") == 0" name;
1724       if name <> name2 then
1725         pr " || strcasecmp (cmd, \"%s\") == 0" name2;
1726       if name <> alias then
1727         pr " || strcasecmp (cmd, \"%s\") == 0" alias;
1728       pr ")\n";
1729       pr "    return run_%s (cmd, argc, argv);\n" name;
1730       pr "  else\n";
1731   ) all_functions;
1732   pr "    {\n";
1733   pr "      fprintf (stderr, \"%%s: unknown command\\n\", cmd);\n";
1734   pr "      return -1;\n";
1735   pr "    }\n";
1736   pr "  return 0;\n";
1737   pr "}\n";
1738   pr "\n"
1739
1740 (* Generate the POD documentation for guestfish. *)
1741 and generate_fish_actions_pod () =
1742   let all_functions_sorted =
1743     List.filter (
1744       fun (_, _, _, flags, _, _) -> not (List.mem NotInFish flags)
1745     ) all_functions_sorted in
1746
1747   List.iter (
1748     fun (name, style, _, flags, _, longdesc) ->
1749       let longdesc = replace_str longdesc "C<guestfs_" "C<" in
1750       let name = replace_char name '_' '-' in
1751       let alias =
1752         try find_map (function FishAlias n -> Some n | _ -> None) flags
1753         with Not_found -> name in
1754
1755       pr "=head2 %s" name;
1756       if name <> alias then
1757         pr " | %s" alias;
1758       pr "\n";
1759       pr "\n";
1760       pr " %s" name;
1761       List.iter (
1762         function
1763         | String n -> pr " %s" n
1764         | OptString n -> pr " %s" n
1765         | Bool _ -> pr " true|false"
1766         | Int n -> pr " %s" n
1767       ) (snd style);
1768       pr "\n";
1769       pr "\n";
1770       pr "%s\n\n" longdesc
1771   ) all_functions_sorted
1772
1773 (* Generate a C function prototype. *)
1774 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
1775     ?(single_line = false) ?(newline = false) ?(in_daemon = false)
1776     ?(prefix = "")
1777     ?handle name style =
1778   if extern then pr "extern ";
1779   if static then pr "static ";
1780   (match fst style with
1781    | Err -> pr "int "
1782    | RInt _ -> pr "int "
1783    | RBool _ -> pr "int "
1784    | RConstString _ -> pr "const char *"
1785    | RString _ -> pr "char *"
1786    | RStringList _ -> pr "char **"
1787    | RIntBool _ ->
1788        if not in_daemon then pr "struct guestfs_int_bool *"
1789        else pr "guestfs_%s_ret *" name
1790    | RPVList _ ->
1791        if not in_daemon then pr "struct guestfs_lvm_pv_list *"
1792        else pr "guestfs_lvm_int_pv_list *"
1793    | RVGList _ ->
1794        if not in_daemon then pr "struct guestfs_lvm_vg_list *"
1795        else pr "guestfs_lvm_int_vg_list *"
1796    | RLVList _ ->
1797        if not in_daemon then pr "struct guestfs_lvm_lv_list *"
1798        else pr "guestfs_lvm_int_lv_list *"
1799   );
1800   pr "%s%s (" prefix name;
1801   if handle = None && List.length (snd style) = 0 then
1802     pr "void"
1803   else (
1804     let comma = ref false in
1805     (match handle with
1806      | None -> ()
1807      | Some handle -> pr "guestfs_h *%s" handle; comma := true
1808     );
1809     let next () =
1810       if !comma then (
1811         if single_line then pr ", " else pr ",\n\t\t"
1812       );
1813       comma := true
1814     in
1815     List.iter (
1816       function
1817       | String n -> next (); pr "const char *%s" n
1818       | OptString n -> next (); pr "const char *%s" n
1819       | Bool n -> next (); pr "int %s" n
1820       | Int n -> next (); pr "int %s" n
1821     ) (snd style);
1822   );
1823   pr ")";
1824   if semicolon then pr ";";
1825   if newline then pr "\n"
1826
1827 (* Generate C call arguments, eg "(handle, foo, bar)" *)
1828 and generate_call_args ?handle style =
1829   pr "(";
1830   let comma = ref false in
1831   (match handle with
1832    | None -> ()
1833    | Some handle -> pr "%s" handle; comma := true
1834   );
1835   List.iter (
1836     fun arg ->
1837       if !comma then pr ", ";
1838       comma := true;
1839       match arg with
1840       | String n -> pr "%s" n
1841       | OptString n -> pr "%s" n
1842       | Bool n -> pr "%s" n
1843       | Int n -> pr "%s" n
1844   ) (snd style);
1845   pr ")"
1846
1847 (* Generate the OCaml bindings interface. *)
1848 and generate_ocaml_mli () =
1849   generate_header OCamlStyle LGPLv2;
1850
1851   pr "\
1852 (** For API documentation you should refer to the C API
1853     in the guestfs(3) manual page.  The OCaml API uses almost
1854     exactly the same calls. *)
1855
1856 type t
1857 (** A [guestfs_h] handle. *)
1858
1859 exception Error of string
1860 (** This exception is raised when there is an error. *)
1861
1862 val create : unit -> t
1863
1864 val close : t -> unit
1865 (** Handles are closed by the garbage collector when they become
1866     unreferenced, but callers can also call this in order to
1867     provide predictable cleanup. *)
1868
1869 ";
1870   generate_ocaml_lvm_structure_decls ();
1871
1872   (* The actions. *)
1873   List.iter (
1874     fun (name, style, _, _, shortdesc, _) ->
1875       generate_ocaml_prototype name style;
1876       pr "(** %s *)\n" shortdesc;
1877       pr "\n"
1878   ) all_functions
1879
1880 (* Generate the OCaml bindings implementation. *)
1881 and generate_ocaml_ml () =
1882   generate_header OCamlStyle LGPLv2;
1883
1884   pr "\
1885 type t
1886 exception Error of string
1887 external create : unit -> t = \"ocaml_guestfs_create\"
1888 external close : t -> unit = \"ocaml_guestfs_close\"
1889
1890 let () =
1891   Callback.register_exception \"ocaml_guestfs_error\" (Error \"\")
1892
1893 ";
1894
1895   generate_ocaml_lvm_structure_decls ();
1896
1897   (* The actions. *)
1898   List.iter (
1899     fun (name, style, _, _, shortdesc, _) ->
1900       generate_ocaml_prototype ~is_external:true name style;
1901   ) all_functions
1902
1903 (* Generate the OCaml bindings C implementation. *)
1904 and generate_ocaml_c () =
1905   generate_header CStyle LGPLv2;
1906
1907   pr "#include <stdio.h>\n";
1908   pr "#include <stdlib.h>\n";
1909   pr "#include <string.h>\n";
1910   pr "\n";
1911   pr "#include <caml/config.h>\n";
1912   pr "#include <caml/alloc.h>\n";
1913   pr "#include <caml/callback.h>\n";
1914   pr "#include <caml/fail.h>\n";
1915   pr "#include <caml/memory.h>\n";
1916   pr "#include <caml/mlvalues.h>\n";
1917   pr "#include <caml/signals.h>\n";
1918   pr "\n";
1919   pr "#include <guestfs.h>\n";
1920   pr "\n";
1921   pr "#include \"guestfs_c.h\"\n";
1922   pr "\n";
1923
1924   (* LVM struct copy functions. *)
1925   List.iter (
1926     fun (typ, cols) ->
1927       let has_optpercent_col =
1928         List.exists (function (_, `OptPercent) -> true | _ -> false) cols in
1929
1930       pr "static CAMLprim value\n";
1931       pr "copy_lvm_%s (const struct guestfs_lvm_%s *%s)\n" typ typ typ;
1932       pr "{\n";
1933       pr "  CAMLparam0 ();\n";
1934       if has_optpercent_col then
1935         pr "  CAMLlocal3 (rv, v, v2);\n"
1936       else
1937         pr "  CAMLlocal2 (rv, v);\n";
1938       pr "\n";
1939       pr "  rv = caml_alloc (%d, 0);\n" (List.length cols);
1940       iteri (
1941         fun i col ->
1942           (match col with
1943            | name, `String ->
1944                pr "  v = caml_copy_string (%s->%s);\n" typ name
1945            | name, `UUID ->
1946                pr "  v = caml_alloc_string (32);\n";
1947                pr "  memcpy (String_val (v), %s->%s, 32);\n" typ name
1948            | name, `Bytes
1949            | name, `Int ->
1950                pr "  v = caml_copy_int64 (%s->%s);\n" typ name
1951            | name, `OptPercent ->
1952                pr "  if (%s->%s >= 0) { /* Some %s */\n" typ name name;
1953                pr "    v2 = caml_copy_double (%s->%s);\n" typ name;
1954                pr "    v = caml_alloc (1, 0);\n";
1955                pr "    Store_field (v, 0, v2);\n";
1956                pr "  } else /* None */\n";
1957                pr "    v = Val_int (0);\n";
1958           );
1959           pr "  Store_field (rv, %d, v);\n" i
1960       ) cols;
1961       pr "  CAMLreturn (rv);\n";
1962       pr "}\n";
1963       pr "\n";
1964
1965       pr "static CAMLprim value\n";
1966       pr "copy_lvm_%s_list (const struct guestfs_lvm_%s_list *%ss)\n"
1967         typ typ typ;
1968       pr "{\n";
1969       pr "  CAMLparam0 ();\n";
1970       pr "  CAMLlocal2 (rv, v);\n";
1971       pr "  int i;\n";
1972       pr "\n";
1973       pr "  if (%ss->len == 0)\n" typ;
1974       pr "    CAMLreturn (Atom (0));\n";
1975       pr "  else {\n";
1976       pr "    rv = caml_alloc (%ss->len, 0);\n" typ;
1977       pr "    for (i = 0; i < %ss->len; ++i) {\n" typ;
1978       pr "      v = copy_lvm_%s (&%ss->val[i]);\n" typ typ;
1979       pr "      caml_modify (&Field (rv, i), v);\n";
1980       pr "    }\n";
1981       pr "    CAMLreturn (rv);\n";
1982       pr "  }\n";
1983       pr "}\n";
1984       pr "\n";
1985   ) ["pv", pv_cols; "vg", vg_cols; "lv", lv_cols];
1986
1987   List.iter (
1988     fun (name, style, _, _, _, _) ->
1989       pr "CAMLprim value\n";
1990       pr "ocaml_guestfs_%s (value gv" name;
1991       List.iter (
1992         fun arg -> pr ", value %sv" (name_of_argt arg)
1993       ) (snd style);
1994       pr ")\n";
1995       pr "{\n";
1996       pr "  CAMLparam%d (gv" (1 + (List.length (snd style)));
1997       List.iter (
1998         fun arg -> pr ", %sv" (name_of_argt arg)
1999       ) (snd style);
2000       pr ");\n";
2001       pr "  CAMLlocal1 (rv);\n";
2002       pr "\n";
2003
2004       pr "  guestfs_h *g = Guestfs_val (gv);\n";
2005       pr "  if (g == NULL)\n";
2006       pr "    caml_failwith (\"%s: used handle after closing it\");\n" name;
2007       pr "\n";
2008
2009       List.iter (
2010         function
2011         | String n ->
2012             pr "  const char *%s = String_val (%sv);\n" n n
2013         | OptString n ->
2014             pr "  const char *%s =\n" n;
2015             pr "    %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
2016               n n
2017         | Bool n ->
2018             pr "  int %s = Bool_val (%sv);\n" n n
2019         | Int n ->
2020             pr "  int %s = Int_val (%sv);\n" n n
2021       ) (snd style);
2022       let error_code =
2023         match fst style with
2024         | Err -> pr "  int r;\n"; "-1"
2025         | RInt _ -> pr "  int r;\n"; "-1"
2026         | RBool _ -> pr "  int r;\n"; "-1"
2027         | RConstString _ -> pr "  const char *r;\n"; "NULL"
2028         | RString _ -> pr "  char *r;\n"; "NULL"
2029         | RStringList _ ->
2030             pr "  int i;\n";
2031             pr "  char **r;\n";
2032             "NULL"
2033         | RIntBool _ ->
2034             pr "  struct guestfs_int_bool *r;\n";
2035             "NULL"
2036         | RPVList _ ->
2037             pr "  struct guestfs_lvm_pv_list *r;\n";
2038             "NULL"
2039         | RVGList _ ->
2040             pr "  struct guestfs_lvm_vg_list *r;\n";
2041             "NULL"
2042         | RLVList _ ->
2043             pr "  struct guestfs_lvm_lv_list *r;\n";
2044             "NULL" in
2045       pr "\n";
2046
2047       pr "  caml_enter_blocking_section ();\n";
2048       pr "  r = guestfs_%s " name;
2049       generate_call_args ~handle:"g" style;
2050       pr ";\n";
2051       pr "  caml_leave_blocking_section ();\n";
2052       pr "  if (r == %s)\n" error_code;
2053       pr "    ocaml_guestfs_raise_error (g, \"%s\");\n" name;
2054       pr "\n";
2055
2056       (match fst style with
2057        | Err -> pr "  rv = Val_unit;\n"
2058        | RInt _ -> pr "  rv = Val_int (r);\n"
2059        | RBool _ -> pr "  rv = Val_bool (r);\n"
2060        | RConstString _ -> pr "  rv = caml_copy_string (r);\n"
2061        | RString _ ->
2062            pr "  rv = caml_copy_string (r);\n";
2063            pr "  free (r);\n"
2064        | RStringList _ ->
2065            pr "  rv = caml_copy_string_array ((const char **) r);\n";
2066            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
2067            pr "  free (r);\n"
2068        | RIntBool _ ->
2069            pr "  rv = caml_alloc (2, 0);\n";
2070            pr "  Store_field (rv, 0, Val_int (r->i));\n";
2071            pr "  Store_field (rv, 1, Val_bool (r->b));\n";
2072            pr "  guestfs_free_int_bool (r);\n";
2073        | RPVList _ ->
2074            pr "  rv = copy_lvm_pv_list (r);\n";
2075            pr "  guestfs_free_lvm_pv_list (r);\n";
2076        | RVGList _ ->
2077            pr "  rv = copy_lvm_vg_list (r);\n";
2078            pr "  guestfs_free_lvm_vg_list (r);\n";
2079        | RLVList _ ->
2080            pr "  rv = copy_lvm_lv_list (r);\n";
2081            pr "  guestfs_free_lvm_lv_list (r);\n";
2082       );
2083
2084       pr "  CAMLreturn (rv);\n";
2085       pr "}\n";
2086       pr "\n"
2087   ) all_functions
2088
2089 and generate_ocaml_lvm_structure_decls () =
2090   List.iter (
2091     fun (typ, cols) ->
2092       pr "type lvm_%s = {\n" typ;
2093       List.iter (
2094         function
2095         | name, `String -> pr "  %s : string;\n" name
2096         | name, `UUID -> pr "  %s : string;\n" name
2097         | name, `Bytes -> pr "  %s : int64;\n" name
2098         | name, `Int -> pr "  %s : int64;\n" name
2099         | name, `OptPercent -> pr "  %s : float option;\n" name
2100       ) cols;
2101       pr "}\n";
2102       pr "\n"
2103   ) ["pv", pv_cols; "vg", vg_cols; "lv", lv_cols]
2104
2105 and generate_ocaml_prototype ?(is_external = false) name style =
2106   if is_external then pr "external " else pr "val ";
2107   pr "%s : t -> " name;
2108   List.iter (
2109     function
2110     | String _ -> pr "string -> "
2111     | OptString _ -> pr "string option -> "
2112     | Bool _ -> pr "bool -> "
2113     | Int _ -> pr "int -> "
2114   ) (snd style);
2115   (match fst style with
2116    | Err -> pr "unit" (* all errors are turned into exceptions *)
2117    | RInt _ -> pr "int"
2118    | RBool _ -> pr "bool"
2119    | RConstString _ -> pr "string"
2120    | RString _ -> pr "string"
2121    | RStringList _ -> pr "string array"
2122    | RIntBool _ -> pr "int * bool"
2123    | RPVList _ -> pr "lvm_pv array"
2124    | RVGList _ -> pr "lvm_vg array"
2125    | RLVList _ -> pr "lvm_lv array"
2126   );
2127   if is_external then pr " = \"ocaml_guestfs_%s\"" name;
2128   pr "\n"
2129
2130 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
2131 and generate_perl_xs () =
2132   generate_header CStyle LGPLv2;
2133
2134   pr "\
2135 #include \"EXTERN.h\"
2136 #include \"perl.h\"
2137 #include \"XSUB.h\"
2138
2139 #include <guestfs.h>
2140
2141 #ifndef PRId64
2142 #define PRId64 \"lld\"
2143 #endif
2144
2145 static SV *
2146 my_newSVll(long long val) {
2147 #ifdef USE_64_BIT_ALL
2148   return newSViv(val);
2149 #else
2150   char buf[100];
2151   int len;
2152   len = snprintf(buf, 100, \"%%\" PRId64, val);
2153   return newSVpv(buf, len);
2154 #endif
2155 }
2156
2157 #ifndef PRIu64
2158 #define PRIu64 \"llu\"
2159 #endif
2160
2161 static SV *
2162 my_newSVull(unsigned long long val) {
2163 #ifdef USE_64_BIT_ALL
2164   return newSVuv(val);
2165 #else
2166   char buf[100];
2167   int len;
2168   len = snprintf(buf, 100, \"%%\" PRIu64, val);
2169   return newSVpv(buf, len);
2170 #endif
2171 }
2172
2173 /* XXX Not thread-safe, and in general not safe if the caller is
2174  * issuing multiple requests in parallel (on different guestfs
2175  * handles).  We should use the guestfs_h handle passed to the
2176  * error handle to distinguish these cases.
2177  */
2178 static char *last_error = NULL;
2179
2180 static void
2181 error_handler (guestfs_h *g,
2182                void *data,
2183                const char *msg)
2184 {
2185   if (last_error != NULL) free (last_error);
2186   last_error = strdup (msg);
2187 }
2188
2189 MODULE = Sys::Guestfs  PACKAGE = Sys::Guestfs
2190
2191 guestfs_h *
2192 _create ()
2193    CODE:
2194       RETVAL = guestfs_create ();
2195       if (!RETVAL)
2196         croak (\"could not create guestfs handle\");
2197       guestfs_set_error_handler (RETVAL, error_handler, NULL);
2198  OUTPUT:
2199       RETVAL
2200
2201 void
2202 DESTROY (g)
2203       guestfs_h *g;
2204  PPCODE:
2205       guestfs_close (g);
2206
2207 ";
2208
2209   List.iter (
2210     fun (name, style, _, _, _, _) ->
2211       (match fst style with
2212        | Err -> pr "void\n"
2213        | RInt _ -> pr "SV *\n"
2214        | RBool _ -> pr "SV *\n"
2215        | RConstString _ -> pr "SV *\n"
2216        | RString _ -> pr "SV *\n"
2217        | RStringList _
2218        | RIntBool _
2219        | RPVList _ | RVGList _ | RLVList _ ->
2220            pr "void\n" (* all lists returned implictly on the stack *)
2221       );
2222       (* Call and arguments. *)
2223       pr "%s " name;
2224       generate_call_args ~handle:"g" style;
2225       pr "\n";
2226       pr "      guestfs_h *g;\n";
2227       List.iter (
2228         function
2229         | String n -> pr "      char *%s;\n" n
2230         | OptString n -> pr "      char *%s;\n" n
2231         | Bool n -> pr "      int %s;\n" n
2232         | Int n -> pr "      int %s;\n" n
2233       ) (snd style);
2234       (* Code. *)
2235       (match fst style with
2236        | Err ->
2237            pr " PPCODE:\n";
2238            pr "      if (guestfs_%s " name;
2239            generate_call_args ~handle:"g" style;
2240            pr " == -1)\n";
2241            pr "        croak (\"%s: %%s\", last_error);\n" name
2242        | RInt n
2243        | RBool n ->
2244            pr "PREINIT:\n";
2245            pr "      int %s;\n" n;
2246            pr "   CODE:\n";
2247            pr "      %s = guestfs_%s " n name;
2248            generate_call_args ~handle:"g" style;
2249            pr ";\n";
2250            pr "      if (%s == -1)\n" n;
2251            pr "        croak (\"%s: %%s\", last_error);\n" name;
2252            pr "      RETVAL = newSViv (%s);\n" n;
2253            pr " OUTPUT:\n";
2254            pr "      RETVAL\n"
2255        | RConstString n ->
2256            pr "PREINIT:\n";
2257            pr "      const char *%s;\n" n;
2258            pr "   CODE:\n";
2259            pr "      %s = guestfs_%s " n name;
2260            generate_call_args ~handle:"g" style;
2261            pr ";\n";
2262            pr "      if (%s == NULL)\n" n;
2263            pr "        croak (\"%s: %%s\", last_error);\n" name;
2264            pr "      RETVAL = newSVpv (%s, 0);\n" n;
2265            pr " OUTPUT:\n";
2266            pr "      RETVAL\n"
2267        | RString n ->
2268            pr "PREINIT:\n";
2269            pr "      char *%s;\n" n;
2270            pr "   CODE:\n";
2271            pr "      %s = guestfs_%s " n name;
2272            generate_call_args ~handle:"g" style;
2273            pr ";\n";
2274            pr "      if (%s == NULL)\n" n;
2275            pr "        croak (\"%s: %%s\", last_error);\n" name;
2276            pr "      RETVAL = newSVpv (%s, 0);\n" n;
2277            pr "      free (%s);\n" n;
2278            pr " OUTPUT:\n";
2279            pr "      RETVAL\n"
2280        | RStringList n ->
2281            pr "PREINIT:\n";
2282            pr "      char **%s;\n" n;
2283            pr "      int i, n;\n";
2284            pr " PPCODE:\n";
2285            pr "      %s = guestfs_%s " n name;
2286            generate_call_args ~handle:"g" style;
2287            pr ";\n";
2288            pr "      if (%s == NULL)\n" n;
2289            pr "        croak (\"%s: %%s\", last_error);\n" name;
2290            pr "      for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
2291            pr "      EXTEND (SP, n);\n";
2292            pr "      for (i = 0; i < n; ++i) {\n";
2293            pr "        PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
2294            pr "        free (%s[i]);\n" n;
2295            pr "      }\n";
2296            pr "      free (%s);\n" n;
2297        | RIntBool _ ->
2298            pr "PREINIT:\n";
2299            pr "      struct guestfs_int_bool *r;\n";
2300            pr " PPCODE:\n";
2301            pr "      r = guestfs_%s " name;
2302            generate_call_args ~handle:"g" style;
2303            pr ";\n";
2304            pr "      if (r == NULL)\n";
2305            pr "        croak (\"%s: %%s\", last_error);\n" name;
2306            pr "      EXTEND (SP, 2);\n";
2307            pr "      PUSHs (sv_2mortal (newSViv (r->i)));\n";
2308            pr "      PUSHs (sv_2mortal (newSViv (r->b)));\n";
2309            pr "      guestfs_free_int_bool (r);\n";
2310        | RPVList n ->
2311            generate_perl_lvm_code "pv" pv_cols name style n;
2312        | RVGList n ->
2313            generate_perl_lvm_code "vg" vg_cols name style n;
2314        | RLVList n ->
2315            generate_perl_lvm_code "lv" lv_cols name style n;
2316       );
2317       pr "\n"
2318   ) all_functions
2319
2320 and generate_perl_lvm_code typ cols name style n =
2321   pr "PREINIT:\n";
2322   pr "      struct guestfs_lvm_%s_list *%s;\n" typ n;
2323   pr "      int i;\n";
2324   pr "      HV *hv;\n";
2325   pr " PPCODE:\n";
2326   pr "      %s = guestfs_%s " n name;
2327   generate_call_args ~handle:"g" style;
2328   pr ";\n";
2329   pr "      if (%s == NULL)\n" n;
2330   pr "        croak (\"%s: %%s\", last_error);\n" name;
2331   pr "      EXTEND (SP, %s->len);\n" n;
2332   pr "      for (i = 0; i < %s->len; ++i) {\n" n;
2333   pr "        hv = newHV ();\n";
2334   List.iter (
2335     function
2336     | name, `String ->
2337         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
2338           name (String.length name) n name
2339     | name, `UUID ->
2340         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
2341           name (String.length name) n name
2342     | name, `Bytes ->
2343         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
2344           name (String.length name) n name
2345     | name, `Int ->
2346         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
2347           name (String.length name) n name
2348     | name, `OptPercent ->
2349         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
2350           name (String.length name) n name
2351   ) cols;
2352   pr "        PUSHs (sv_2mortal ((SV *) hv));\n";
2353   pr "      }\n";
2354   pr "      guestfs_free_lvm_%s_list (%s);\n" typ n
2355
2356 (* Generate Sys/Guestfs.pm. *)
2357 and generate_perl_pm () =
2358   generate_header HashStyle LGPLv2;
2359
2360   pr "\
2361 =pod
2362
2363 =head1 NAME
2364
2365 Sys::Guestfs - Perl bindings for libguestfs
2366
2367 =head1 SYNOPSIS
2368
2369  use Sys::Guestfs;
2370  
2371  my $h = Sys::Guestfs->new ();
2372  $h->add_drive ('guest.img');
2373  $h->launch ();
2374  $h->wait_ready ();
2375  $h->mount ('/dev/sda1', '/');
2376  $h->touch ('/hello');
2377  $h->sync ();
2378
2379 =head1 DESCRIPTION
2380
2381 The C<Sys::Guestfs> module provides a Perl XS binding to the
2382 libguestfs API for examining and modifying virtual machine
2383 disk images.
2384
2385 Amongst the things this is good for: making batch configuration
2386 changes to guests, getting disk used/free statistics (see also:
2387 virt-df), migrating between virtualization systems (see also:
2388 virt-p2v), performing partial backups, performing partial guest
2389 clones, cloning guests and changing registry/UUID/hostname info, and
2390 much else besides.
2391
2392 Libguestfs uses Linux kernel and qemu code, and can access any type of
2393 guest filesystem that Linux and qemu can, including but not limited
2394 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
2395 schemes, qcow, qcow2, vmdk.
2396
2397 Libguestfs provides ways to enumerate guest storage (eg. partitions,
2398 LVs, what filesystem is in each LV, etc.).  It can also run commands
2399 in the context of the guest.  Also you can access filesystems over FTP.
2400
2401 =head1 ERRORS
2402
2403 All errors turn into calls to C<croak> (see L<Carp(3)>).
2404
2405 =head1 METHODS
2406
2407 =over 4
2408
2409 =cut
2410
2411 package Sys::Guestfs;
2412
2413 use strict;
2414 use warnings;
2415
2416 require XSLoader;
2417 XSLoader::load ('Sys::Guestfs');
2418
2419 =item $h = Sys::Guestfs->new ();
2420
2421 Create a new guestfs handle.
2422
2423 =cut
2424
2425 sub new {
2426   my $proto = shift;
2427   my $class = ref ($proto) || $proto;
2428
2429   my $self = Sys::Guestfs::_create ();
2430   bless $self, $class;
2431   return $self;
2432 }
2433
2434 ";
2435
2436   (* Actions.  We only need to print documentation for these as
2437    * they are pulled in from the XS code automatically.
2438    *)
2439   List.iter (
2440     fun (name, style, _, flags, _, longdesc) ->
2441       let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
2442       pr "=item ";
2443       generate_perl_prototype name style;
2444       pr "\n\n";
2445       pr "%s\n\n" longdesc;
2446       if List.mem ProtocolLimitWarning flags then
2447         pr "Because of the message protocol, there is a transfer limit 
2448 of somewhere between 2MB and 4MB.  To transfer large files you should use
2449 FTP.\n\n";
2450   ) all_functions_sorted;
2451
2452   (* End of file. *)
2453   pr "\
2454 =cut
2455
2456 1;
2457
2458 =back
2459
2460 =head1 COPYRIGHT
2461
2462 Copyright (C) 2009 Red Hat Inc.
2463
2464 =head1 LICENSE
2465
2466 Please see the file COPYING.LIB for the full license.
2467
2468 =head1 SEE ALSO
2469
2470 L<guestfs(3)>, L<guestfish(1)>.
2471
2472 =cut
2473 "
2474
2475 and generate_perl_prototype name style =
2476   (match fst style with
2477    | Err -> ()
2478    | RBool n
2479    | RInt n
2480    | RConstString n
2481    | RString n -> pr "$%s = " n
2482    | RIntBool (n, m) -> pr "($%s, $%s) = " n m
2483    | RStringList n
2484    | RPVList n
2485    | RVGList n
2486    | RLVList n -> pr "@%s = " n
2487   );
2488   pr "$h->%s (" name;
2489   let comma = ref false in
2490   List.iter (
2491     fun arg ->
2492       if !comma then pr ", ";
2493       comma := true;
2494       pr "%s" (name_of_argt arg)
2495   ) (snd style);
2496   pr ");"
2497
2498 let output_to filename =
2499   let filename_new = filename ^ ".new" in
2500   chan := open_out filename_new;
2501   let close () =
2502     close_out !chan;
2503     chan := stdout;
2504     Unix.rename filename_new filename;
2505     printf "written %s\n%!" filename;
2506   in
2507   close
2508
2509 (* Main program. *)
2510 let () =
2511   check_functions ();
2512
2513   let close = output_to "src/guestfs_protocol.x" in
2514   generate_xdr ();
2515   close ();
2516
2517   let close = output_to "src/guestfs-structs.h" in
2518   generate_structs_h ();
2519   close ();
2520
2521   let close = output_to "src/guestfs-actions.h" in
2522   generate_actions_h ();
2523   close ();
2524
2525   let close = output_to "src/guestfs-actions.c" in
2526   generate_client_actions ();
2527   close ();
2528
2529   let close = output_to "daemon/actions.h" in
2530   generate_daemon_actions_h ();
2531   close ();
2532
2533   let close = output_to "daemon/stubs.c" in
2534   generate_daemon_actions ();
2535   close ();
2536
2537   let close = output_to "fish/cmds.c" in
2538   generate_fish_cmds ();
2539   close ();
2540
2541   let close = output_to "guestfs-structs.pod" in
2542   generate_structs_pod ();
2543   close ();
2544
2545   let close = output_to "guestfs-actions.pod" in
2546   generate_actions_pod ();
2547   close ();
2548
2549   let close = output_to "guestfish-actions.pod" in
2550   generate_fish_actions_pod ();
2551   close ();
2552
2553   let close = output_to "ocaml/guestfs.mli" in
2554   generate_ocaml_mli ();
2555   close ();
2556
2557   let close = output_to "ocaml/guestfs.ml" in
2558   generate_ocaml_ml ();
2559   close ();
2560
2561   let close = output_to "ocaml/guestfs_c_actions.c" in
2562   generate_ocaml_c ();
2563   close ();
2564
2565   let close = output_to "perl/Guestfs.xs" in
2566   generate_perl_xs ();
2567   close ();
2568
2569   let close = output_to "perl/lib/Sys/Guestfs.pm" in
2570   generate_perl_pm ();
2571   close ();