2 * Copyright (C) 2009-2011 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;
297 | RErr | RInt _ | RBool _ -> pr " int r;\n"
298 | RInt64 _ -> pr " int64_t r;\n"
299 | RConstString _ | RConstOptString _ ->
300 pr " const char *r;\n"
301 | RString _ -> pr " char *r;\n"
302 | RStringList _ | RHashtable _ -> pr " char **r;\n"
303 | RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ
304 | RStructList (_, typ) ->
305 pr " struct guestfs_%s_list *r;\n" typ
313 | Pathname n | Device n | Dev_or_Path n | String n | Key n
314 | FileIn n | FileOut n ->
315 pr " const char *%s;\n" n
316 | OptString n -> pr " const char *%s;\n" n
318 pr " const char *%s;\n" n;
319 pr " Py_ssize_t %s_size;\n" n
320 | StringList n | DeviceList n ->
321 pr " PyObject *py_%s;\n" n;
323 | Bool n -> pr " int %s;\n" n
324 | Int n -> pr " int %s;\n" n
325 | Int64 n -> pr " long long %s;\n" n
327 pr " long long %s_int64;\n" n;
331 if optargs <> [] then (
332 (* XXX This is horrible. We have to use sentinel values on the
333 * Python side to denote values not set.
335 (* Since we don't know if Python types will exactly match
336 * structure types, declare some local variables here.
341 | Int n -> pr " int optargs_t_%s = -1;\n" n
342 | Int64 n -> pr " long long optargs_t_%s = -1;\n" n
343 | String n -> pr " const char *optargs_t_%s = NULL;\n" n
350 if optargs <> [] then (
351 pr " optargs_s.bitmask = 0;\n";
355 (* Convert the required parameters. *)
356 pr " if (!PyArg_ParseTuple (args, (char *) \"O";
359 | Pathname _ | Device _ | Dev_or_Path _ | String _ | Key _
360 | FileIn _ | FileOut _ -> pr "s"
361 | OptString _ -> pr "z"
362 | StringList _ | DeviceList _ -> pr "O"
363 | Bool _ -> pr "i" (* XXX Python has booleans? *)
365 | Int64 _ | Pointer _ ->
366 (* XXX Whoever thought it was a good idea to
367 * emulate C's int/long/long long in Python?
370 | BufferIn _ -> pr "s#"
373 (* Optional parameters. *)
374 if optargs <> [] then (
377 | Bool _ | Int _ -> pr "i"
379 | String _ -> pr "z" (* because we use None to mean not set *)
384 pr ":guestfs_%s\",\n" name;
388 | Pathname n | Device n | Dev_or_Path n | String n | Key n
389 | FileIn n | FileOut n -> pr ", &%s" n
390 | OptString n -> pr ", &%s" n
391 | StringList n | DeviceList n -> pr ", &py_%s" n
392 | Bool n -> pr ", &%s" n
393 | Int n -> pr ", &%s" n
394 | Int64 n -> pr ", &%s" n
395 | Pointer (_, n) -> pr ", &%s_int64" n
396 | BufferIn n -> pr ", &%s, &%s_size" n n
401 | Bool n | Int n | Int64 n | String n -> pr ", &optargs_t_%s" n
406 pr " return NULL;\n";
408 pr " g = get_handle (py_g);\n";
411 | Pathname _ | Device _ | Dev_or_Path _ | String _ | Key _
412 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
414 | StringList n | DeviceList n ->
415 pr " %s = get_string_list (py_%s);\n" n n;
416 pr " if (!%s) return NULL;\n" n
418 pr " %s = (%s) (intptr_t) %s_int64;\n" n t n
423 if optargs <> [] then (
424 let uc_name = String.uppercase name in
427 let n = name_of_argt argt in
428 let uc_n = String.uppercase n in
429 pr " if (optargs_t_%s != " n;
431 | Bool _ | Int _ | Int64 _ -> pr "-1"
432 | String _ -> pr "NULL"
436 pr " optargs_s.%s = optargs_t_%s;\n" n n;
437 pr " optargs_s.bitmask |= GUESTFS_%s_%s_BITMASK;\n" uc_name uc_n;
444 pr " r = guestfs_%s " name
446 pr " r = guestfs_%s_argv " name;
447 generate_c_call_args ~handle:"g" style;
452 | Pathname _ | Device _ | Dev_or_Path _ | String _ | Key _
453 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
454 | BufferIn _ | Pointer _ -> ()
455 | StringList n | DeviceList n ->
459 (match errcode_of_ret ret with
460 | `CannotReturnError -> ()
461 | `ErrorIsMinusOne ->
462 pr " if (r == -1) {\n";
463 pr " PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
464 pr " return NULL;\n";
467 pr " if (r == NULL) {\n";
468 pr " PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
469 pr " return NULL;\n";
476 pr " Py_INCREF (Py_None);\n";
477 pr " py_r = Py_None;\n"
479 | RBool _ -> pr " py_r = PyInt_FromLong ((long) r);\n"
480 | RInt64 _ -> pr " py_r = PyLong_FromLongLong (r);\n"
481 | RConstString _ -> pr " py_r = PyString_FromString (r);\n"
482 | RConstOptString _ ->
484 pr " py_r = PyString_FromString (r);\n";
486 pr " Py_INCREF (Py_None);\n";
487 pr " py_r = Py_None;\n";
490 pr " py_r = PyString_FromString (r);\n";
493 pr " py_r = put_string_list (r);\n";
494 pr " free_strings (r);\n"
495 | RStruct (_, typ) ->
496 pr " py_r = put_%s (r);\n" typ;
497 pr " guestfs_free_%s (r);\n" typ
498 | RStructList (_, typ) ->
499 pr " py_r = put_%s_list (r);\n" typ;
500 pr " guestfs_free_%s_list (r);\n" typ
502 pr " py_r = put_table (r);\n";
503 pr " free_strings (r);\n"
505 pr " py_r = PyString_FromStringAndSize (r, size);\n";
509 pr " return py_r;\n";
514 (* Table of functions. *)
515 pr "static PyMethodDef methods[] = {\n";
516 pr " { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
517 pr " { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
519 fun (name, _, _, _, _, _, _) ->
520 pr " { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
523 pr " { NULL, NULL, 0, NULL }\n";
530 initlibguestfsmod (void)
532 static int initialized = 0;
534 if (initialized) return;
535 Py_InitModule ((char *) \"libguestfsmod\", methods);
540 (* Generate Python module. *)
541 and generate_python_py () =
542 generate_header HashStyle LGPLv2plus;
545 u\"\"\"Python bindings for libguestfs
548 g = guestfs.GuestFS ()
549 g.add_drive_opts (\"guest.img\", format=\"raw\")
551 parts = g.list_partitions ()
553 The guestfs module provides a Python binding to the libguestfs API
554 for examining and modifying virtual machine disk images.
556 Amongst the things this is good for: making batch configuration
557 changes to guests, getting disk used/free statistics (see also:
558 virt-df), migrating between virtualization systems (see also:
559 virt-p2v), performing partial backups, performing partial guest
560 clones, cloning guests and changing registry/UUID/hostname info, and
563 Libguestfs uses Linux kernel and qemu code, and can access any type of
564 guest filesystem that Linux and qemu can, including but not limited
565 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
566 schemes, qcow, qcow2, vmdk.
568 Libguestfs provides ways to enumerate guest storage (eg. partitions,
569 LVs, what filesystem is in each LV, etc.). It can also run commands
570 in the context of the guest. Also you can access filesystems over
573 Errors which happen while using the API are turned into Python
574 RuntimeError exceptions.
576 To create a guestfs handle you usually have to perform the following
579 # Create the handle, call add_drive* at least once, and possibly
580 # several times if the guest has multiple block devices:
581 g = guestfs.GuestFS ()
582 g.add_drive_opts (\"guest.img\", format=\"raw\")
584 # Launch the qemu subprocess and wait for it to become ready:
587 # Now you can issue commands, for example:
595 \"\"\"Instances of this class are libguestfs API handles.\"\"\"
598 \"\"\"Create a new libguestfs handle.\"\"\"
599 self._o = libguestfsmod.create ()
602 libguestfsmod.close (self._o)
607 fun (name, (ret, args, optargs), _, flags, _, _, longdesc) ->
608 pr " def %s (self" name;
609 List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
612 | Bool n | Int n | Int64 n -> pr ", %s=-1" n
613 | String n -> pr ", %s=None" n
618 if not (List.mem NotInDocs flags) then (
619 let doc = replace_str longdesc "C<guestfs_" "C<g." in
622 | RErr | RInt _ | RInt64 _ | RBool _
623 | RConstOptString _ | RConstString _
624 | RString _ | RBufferOut _ -> doc
626 doc ^ "\n\nThis function returns a list of strings."
627 | RStruct (_, typ) ->
628 doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
629 | RStructList (_, typ) ->
630 doc ^ sprintf "\n\nThis function returns a list of %ss. Each %s is represented as a dictionary." typ typ
632 doc ^ "\n\nThis function returns a dictionary." in
634 if List.mem ProtocolLimitWarning flags then
635 doc ^ "\n\n" ^ protocol_limit_warning
638 if List.mem DangerWillRobinson flags then
639 doc ^ "\n\n" ^ danger_will_robinson
642 match deprecation_notice flags with
644 | Some txt -> doc ^ "\n\n" ^ txt in
645 let doc = pod2text ~width:60 name doc in
646 let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
647 let doc = String.concat "\n " doc in
648 pr " u\"\"\"%s\"\"\"\n" doc;
650 (* Callers might pass in iterables instead of plain lists;
651 * convert those to plain lists because the C side of things
652 * cannot deal with iterables. (RHBZ#693306).
656 | Pathname _ | Device _ | Dev_or_Path _ | String _ | Key _
657 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
658 | BufferIn _ | Pointer _ -> ()
659 | StringList n | DeviceList n ->
660 pr " %s = list (%s)\n" n n
662 pr " return libguestfsmod.%s (self._o" name;
663 List.iter (fun arg -> pr ", %s" (name_of_argt arg)) (args@optargs);