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