2 * Copyright (C) 2009-2010 Red Hat Inc.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 (* Please read generator/README first. *)
26 open Generator_docstrings
27 open Generator_optgroups
28 open Generator_actions
29 open Generator_structs
32 (* Generate Python C module. *)
33 let rec generate_python_c () =
34 generate_header CStyle LGPLv2plus;
37 #define PY_SSIZE_T_CLEAN 1
40 #if PY_VERSION_HEX < 0x02050000
41 typedef int Py_ssize_t;
42 #define PY_SSIZE_T_MAX INT_MAX
43 #define PY_SSIZE_T_MIN INT_MIN
50 #include \"guestfs.h\"
52 #ifndef HAVE_PYCAPSULE_NEW
60 get_handle (PyObject *obj)
63 assert (obj != Py_None);
64 #ifndef HAVE_PYCAPSULE_NEW
65 return ((Pyguestfs_Object *) obj)->g;
67 return (guestfs_h*) PyCapsule_GetPointer(obj, \"guestfs_h\");
72 put_handle (guestfs_h *g)
75 #ifndef HAVE_PYCAPSULE_NEW
77 PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
79 return PyCapsule_New ((void *) g, \"guestfs_h\", NULL);
83 /* This list should be freed (but not the strings) after use. */
85 get_string_list (PyObject *obj)
92 if (!PyList_Check (obj)) {
93 PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
97 Py_ssize_t slen = PyList_Size (obj);
99 PyErr_SetString (PyExc_RuntimeError, \"get_string_list: PyList_Size failure\");
103 r = malloc (sizeof (char *) * (len+1));
105 PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
109 for (i = 0; i < len; ++i)
110 r[i] = PyString_AsString (PyList_GetItem (obj, i));
117 put_string_list (char * const * const argv)
122 for (argc = 0; argv[argc] != NULL; ++argc)
125 list = PyList_New (argc);
126 for (i = 0; i < argc; ++i)
127 PyList_SetItem (list, i, PyString_FromString (argv[i]));
133 put_table (char * const * const argv)
135 PyObject *list, *item;
138 for (argc = 0; argv[argc] != NULL; ++argc)
141 list = PyList_New (argc >> 1);
142 for (i = 0; i < argc; i += 2) {
143 item = PyTuple_New (2);
144 PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
145 PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
146 PyList_SetItem (list, i >> 1, item);
153 free_strings (char **argv)
157 for (argc = 0; argv[argc] != NULL; ++argc)
163 py_guestfs_create (PyObject *self, PyObject *args)
167 g = guestfs_create ();
169 PyErr_SetString (PyExc_RuntimeError,
170 \"guestfs.create: failed to allocate handle\");
173 guestfs_set_error_handler (g, NULL, NULL);
174 /* This can return NULL, but in that case put_handle will have
175 * set the Python error string.
177 return put_handle (g);
181 py_guestfs_close (PyObject *self, PyObject *args)
186 if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
188 g = get_handle (py_g);
198 let emit_put_list_function typ =
199 pr "static PyObject *\n";
200 pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
202 pr " PyObject *list;\n";
205 pr " list = PyList_New (%ss->len);\n" typ;
206 pr " for (i = 0; i < %ss->len; ++i)\n" typ;
207 pr " PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
208 pr " return list;\n";
213 (* Structures, turned into Python dictionaries. *)
216 pr "static PyObject *\n";
217 pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
219 pr " PyObject *dict;\n";
221 pr " dict = PyDict_New ();\n";
225 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
226 pr " PyString_FromString (%s->%s));\n"
229 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
230 pr " PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
233 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
234 pr " PyString_FromStringAndSize (%s->%s, 32));\n"
236 | name, (FBytes|FUInt64) ->
237 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
238 pr " PyLong_FromUnsignedLongLong (%s->%s));\n"
241 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
242 pr " PyLong_FromLongLong (%s->%s));\n"
245 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
246 pr " PyLong_FromUnsignedLong (%s->%s));\n"
249 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
250 pr " PyLong_FromLong (%s->%s));\n"
252 | name, FOptPercent ->
253 pr " if (%s->%s >= 0)\n" typ name;
254 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
255 pr " PyFloat_FromDouble ((double) %s->%s));\n"
258 pr " Py_INCREF (Py_None);\n";
259 pr " PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
262 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
263 pr " PyString_FromStringAndSize (&dirent->%s, 1));\n" name
265 pr " return dict;\n";
271 (* Emit a put_TYPE_list function definition only if that function is used. *)
274 | typ, (RStructListOnly | RStructAndList) ->
275 (* generate the function for typ *)
276 emit_put_list_function typ
277 | typ, _ -> () (* empty *)
278 ) (rstructs_used_by all_functions);
280 (* Python wrapper functions. *)
282 fun (name, (ret, args, optargs as style), _, _, _, _, _) ->
283 pr "static PyObject *\n";
284 pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
287 pr " PyObject *py_g;\n";
288 pr " guestfs_h *g;\n";
289 pr " PyObject *py_r;\n";
291 if optargs <> [] then (
292 pr " struct guestfs_%s_argv optargs_s;\n" name;
293 pr " struct guestfs_%s_argv *optargs = &optargs_s;\n" name;
298 | RErr | RInt _ | RBool _ -> pr " int r;\n"; "-1"
299 | RInt64 _ -> pr " int64_t r;\n"; "-1"
300 | RConstString _ | RConstOptString _ ->
301 pr " const char *r;\n"; "NULL"
302 | RString _ -> pr " char *r;\n"; "NULL"
303 | RStringList _ | RHashtable _ -> pr " char **r;\n"; "NULL"
304 | RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ; "NULL"
305 | RStructList (_, typ) ->
306 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
309 pr " size_t size;\n";
314 | Pathname n | Device n | Dev_or_Path n | String n | Key n
315 | FileIn n | FileOut n ->
316 pr " const char *%s;\n" n
317 | OptString n -> pr " const char *%s;\n" n
319 pr " const char *%s;\n" n;
320 pr " Py_ssize_t %s_size;\n" n
321 | StringList n | DeviceList n ->
322 pr " PyObject *py_%s;\n" n;
324 | Bool n -> pr " int %s;\n" n
325 | Int n -> pr " int %s;\n" n
326 | Int64 n -> pr " long long %s;\n" n
328 pr " long long %s_int64;\n" n;
332 if optargs <> [] then (
333 (* XXX This is horrible. We have to use sentinel values on the
334 * Python side to denote values not set.
336 (* Since we don't know if Python types will exactly match
337 * structure types, declare some local variables here.
342 | Int n -> pr " int optargs_t_%s = -1;\n" n
343 | Int64 n -> pr " long long optargs_t_%s = -1;\n" n
344 | String n -> pr " const char *optargs_t_%s = NULL;\n" n
351 if optargs <> [] then (
352 pr " optargs_s.bitmask = 0;\n";
356 (* Convert the required parameters. *)
357 pr " if (!PyArg_ParseTuple (args, (char *) \"O";
360 | Pathname _ | Device _ | Dev_or_Path _ | String _ | Key _
361 | FileIn _ | FileOut _ -> pr "s"
362 | OptString _ -> pr "z"
363 | StringList _ | DeviceList _ -> pr "O"
364 | Bool _ -> pr "i" (* XXX Python has booleans? *)
366 | Int64 _ | Pointer _ ->
367 (* XXX Whoever thought it was a good idea to
368 * emulate C's int/long/long long in Python?
371 | BufferIn _ -> pr "s#"
374 (* Optional parameters. *)
375 if optargs <> [] then (
378 | Bool _ | Int _ -> pr "i"
380 | String _ -> pr "z" (* because we use None to mean not set *)
385 pr ":guestfs_%s\",\n" name;
389 | Pathname n | Device n | Dev_or_Path n | String n | Key n
390 | FileIn n | FileOut n -> pr ", &%s" n
391 | OptString n -> pr ", &%s" n
392 | StringList n | DeviceList n -> pr ", &py_%s" n
393 | Bool n -> pr ", &%s" n
394 | Int n -> pr ", &%s" n
395 | Int64 n -> pr ", &%s" n
396 | Pointer (_, n) -> pr ", &%s_int64" n
397 | BufferIn n -> pr ", &%s, &%s_size" n n
402 | Bool n | Int n | Int64 n | String n -> pr ", &optargs_t_%s" n
407 pr " return NULL;\n";
409 pr " g = get_handle (py_g);\n";
412 | Pathname _ | Device _ | Dev_or_Path _ | String _ | Key _
413 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
415 | StringList n | DeviceList n ->
416 pr " %s = get_string_list (py_%s);\n" n n;
417 pr " if (!%s) return NULL;\n" n
419 pr " %s = (%s) (intptr_t) %s_int64;\n" n t n
424 if optargs <> [] then (
425 let uc_name = String.uppercase name in
428 let n = name_of_argt argt in
429 let uc_n = String.uppercase n in
430 pr " if (optargs_t_%s != " n;
432 | Bool _ | Int _ | Int64 _ -> pr "-1"
433 | String _ -> pr "NULL"
437 pr " optargs_s.%s = optargs_t_%s;\n" n n;
438 pr " optargs_s.bitmask |= GUESTFS_%s_%s_BITMASK;\n" uc_name uc_n;
445 pr " r = guestfs_%s " name
447 pr " r = guestfs_%s_argv " name;
448 generate_c_call_args ~handle:"g" style;
453 | Pathname _ | Device _ | Dev_or_Path _ | String _ | Key _
454 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
455 | BufferIn _ | Pointer _ -> ()
456 | StringList n | DeviceList n ->
460 pr " if (r == %s) {\n" error_code;
461 pr " PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
462 pr " return NULL;\n";
468 pr " Py_INCREF (Py_None);\n";
469 pr " py_r = Py_None;\n"
471 | RBool _ -> pr " py_r = PyInt_FromLong ((long) r);\n"
472 | RInt64 _ -> pr " py_r = PyLong_FromLongLong (r);\n"
473 | RConstString _ -> pr " py_r = PyString_FromString (r);\n"
474 | RConstOptString _ ->
476 pr " py_r = PyString_FromString (r);\n";
478 pr " Py_INCREF (Py_None);\n";
479 pr " py_r = Py_None;\n";
482 pr " py_r = PyString_FromString (r);\n";
485 pr " py_r = put_string_list (r);\n";
486 pr " free_strings (r);\n"
487 | RStruct (_, typ) ->
488 pr " py_r = put_%s (r);\n" typ;
489 pr " guestfs_free_%s (r);\n" typ
490 | RStructList (_, typ) ->
491 pr " py_r = put_%s_list (r);\n" typ;
492 pr " guestfs_free_%s_list (r);\n" typ
494 pr " py_r = put_table (r);\n";
495 pr " free_strings (r);\n"
497 pr " py_r = PyString_FromStringAndSize (r, size);\n";
501 pr " return py_r;\n";
506 (* Table of functions. *)
507 pr "static PyMethodDef methods[] = {\n";
508 pr " { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
509 pr " { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
511 fun (name, _, _, _, _, _, _) ->
512 pr " { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
515 pr " { NULL, NULL, 0, NULL }\n";
522 initlibguestfsmod (void)
524 static int initialized = 0;
526 if (initialized) return;
527 Py_InitModule ((char *) \"libguestfsmod\", methods);
532 (* Generate Python module. *)
533 and generate_python_py () =
534 generate_header HashStyle LGPLv2plus;
537 u\"\"\"Python bindings for libguestfs
540 g = guestfs.GuestFS ()
541 g.add_drive_opts (\"guest.img\", format=\"raw\")
543 parts = g.list_partitions ()
545 The guestfs module provides a Python binding to the libguestfs API
546 for examining and modifying virtual machine disk images.
548 Amongst the things this is good for: making batch configuration
549 changes to guests, getting disk used/free statistics (see also:
550 virt-df), migrating between virtualization systems (see also:
551 virt-p2v), performing partial backups, performing partial guest
552 clones, cloning guests and changing registry/UUID/hostname info, and
555 Libguestfs uses Linux kernel and qemu code, and can access any type of
556 guest filesystem that Linux and qemu can, including but not limited
557 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
558 schemes, qcow, qcow2, vmdk.
560 Libguestfs provides ways to enumerate guest storage (eg. partitions,
561 LVs, what filesystem is in each LV, etc.). It can also run commands
562 in the context of the guest. Also you can access filesystems over
565 Errors which happen while using the API are turned into Python
566 RuntimeError exceptions.
568 To create a guestfs handle you usually have to perform the following
571 # Create the handle, call add_drive* at least once, and possibly
572 # several times if the guest has multiple block devices:
573 g = guestfs.GuestFS ()
574 g.add_drive_opts (\"guest.img\", format=\"raw\")
576 # Launch the qemu subprocess and wait for it to become ready:
579 # Now you can issue commands, for example:
587 \"\"\"Instances of this class are libguestfs API handles.\"\"\"
590 \"\"\"Create a new libguestfs handle.\"\"\"
591 self._o = libguestfsmod.create ()
594 libguestfsmod.close (self._o)
599 fun (name, (ret, args, optargs), _, flags, _, _, longdesc) ->
600 pr " def %s (self" name;
601 List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
604 | Bool n | Int n | Int64 n -> pr ", %s=-1" n
605 | String n -> pr ", %s=None" n
610 if not (List.mem NotInDocs flags) then (
611 let doc = replace_str longdesc "C<guestfs_" "C<g." in
614 | RErr | RInt _ | RInt64 _ | RBool _
615 | RConstOptString _ | RConstString _
616 | RString _ | RBufferOut _ -> doc
618 doc ^ "\n\nThis function returns a list of strings."
619 | RStruct (_, typ) ->
620 doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
621 | RStructList (_, typ) ->
622 doc ^ sprintf "\n\nThis function returns a list of %ss. Each %s is represented as a dictionary." typ typ
624 doc ^ "\n\nThis function returns a dictionary." in
626 if List.mem ProtocolLimitWarning flags then
627 doc ^ "\n\n" ^ protocol_limit_warning
630 if List.mem DangerWillRobinson flags then
631 doc ^ "\n\n" ^ danger_will_robinson
634 match deprecation_notice flags with
636 | Some txt -> doc ^ "\n\n" ^ txt in
637 let doc = pod2text ~width:60 name doc in
638 let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
639 let doc = String.concat "\n " doc in
640 pr " u\"\"\"%s\"\"\"\n" doc;
642 pr " return libguestfsmod.%s (self._o" name;
643 List.iter (fun arg -> pr ", %s" (name_of_argt arg)) (args@optargs);