Rename global 'xdr_str'.
[libguestfs.git] / src / generator.ml
index f32e064..dac2fd1 100755 (executable)
@@ -548,15 +548,13 @@ handle is closed.  We don't currently have any method to enable
 changes to be committed, although qemu can support this.
 
 This is equivalent to the qemu parameter
-C<-drive file=filename,snapshot=on,readonly=on,if=...>.
+C<-drive file=filename,snapshot=on,if=...>.
 
 C<if=...> is set at compile time by the configuration option
 C<./configure --with-drive-if=...>.  In the rare case where you
 might need to change this at run time, use C<guestfs_add_drive_with_if>
 or C<guestfs_add_drive_ro_with_if>.
 
-C<readonly=on> is only added where qemu supports this option.
-
 Note that this call checks for the existence of C<filename>.  This
 stops you from specifying other types of drive which are supported
 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
@@ -5238,7 +5236,7 @@ let rec generate_actions_pod () =
 The string is owned by the guest handle and must I<not> be freed.\n\n"
          | RConstOptString _ ->
              pr "This function returns a string which may be NULL.
-There is way to return an error from this function.
+There is no way to return an error from this function.
 The string is owned by the guest handle and must I<not> be freed.\n\n"
          | RString _ ->
              pr "This function returns a string, or NULL on error.
@@ -5343,7 +5341,7 @@ and generate_xdr () =
   generate_header CStyle LGPLv2plus;
 
   (* This has to be defined to get around a limitation in Sun's rpcgen. *)
-  pr "typedef string str<>;\n";
+  pr "typedef string guestfs_str<>;\n";
   pr "\n";
 
   (* Internal structures. *)
@@ -5378,8 +5376,8 @@ and generate_xdr () =
              function
              | Pathname n | Device n | Dev_or_Path n | String n ->
                  pr "  string %s<>;\n" n
-             | OptString n -> pr "  str *%s;\n" n
-             | StringList n | DeviceList n -> pr "  str %s<>;\n" n
+             | OptString n -> pr "  guestfs_str *%s;\n" n
+             | StringList n | DeviceList n -> pr "  guestfs_str %s<>;\n" n
              | Bool n -> pr "  bool %s;\n" n
              | Int n -> pr "  int %s;\n" n
              | Int64 n -> pr "  hyper %s;\n" n
@@ -5409,7 +5407,7 @@ and generate_xdr () =
            pr "};\n\n"
        | RStringList n ->
            pr "struct %s_ret {\n" name;
-           pr "  str %s<>;\n" n;
+           pr "  guestfs_str %s<>;\n" n;
            pr "};\n\n"
        | RStruct (n, typ) ->
            pr "struct %s_ret {\n" name;
@@ -5421,7 +5419,7 @@ and generate_xdr () =
            pr "};\n\n"
        | RHashtable n ->
            pr "struct %s_ret {\n" name;
-           pr "  str %s<>;\n" n;
+           pr "  guestfs_str %s<>;\n" n;
            pr "};\n\n"
        | RBufferOut n ->
            pr "struct %s_ret {\n" name;
@@ -5645,7 +5643,7 @@ check_state (guestfs_h *g, const char *caller)
                    | StringList _ | DeviceList _ -> true
                    | _ -> false) (snd style) in
     if needs_i then (
-      pr "    int i;\n";
+      pr "    size_t i;\n";
       pr "\n"
     );
 
@@ -5954,6 +5952,8 @@ and generate_linker_script () =
      *)
     "guestfs_safe_calloc";
     "guestfs_safe_malloc";
+    "guestfs_safe_strdup";
+    "guestfs_safe_memdup";
   ] in
   let functions =
     List.map (fun (name, _, _, _, _, _, _) -> "guestfs_" ^ name)
@@ -6074,9 +6074,12 @@ and generate_daemon_actions () =
              | DeviceList n ->
                  pr_list_handling_code n;
                  pr "  /* Ensure that each is a device,\n";
-                 pr "   * and perform device name translation. */\n";
-                 pr "  { int pvi; for (pvi = 0; physvols[pvi] != NULL; ++pvi)\n";
-                 pr "    RESOLVE_DEVICE (physvols[pvi], goto done);\n";
+                 pr "   * and perform device name translation.\n";
+                 pr "   */\n";
+                 pr "  {\n";
+                 pr "    size_t i;\n";
+                 pr "    for (i = 0; %s[i] != NULL; ++i)\n" n;
+                 pr "      RESOLVE_DEVICE (%s[i], goto done);\n" n;
                  pr "  }\n";
              | Bool n -> pr "  %s = args.%s;\n" n n
              | Int n -> pr "  %s = args.%s;\n" n n
@@ -6221,7 +6224,7 @@ and generate_daemon_actions () =
         pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
         pr "{\n";
         pr "  char *tok, *p, *next;\n";
-        pr "  int i, j;\n";
+        pr "  size_t i, j;\n";
         pr "\n";
         (*
           pr "  fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
@@ -6446,7 +6449,7 @@ static void print_error (guestfs_h *g, void *data, const char *msg)
 /* FIXME: nearly identical code appears in fish.c */
 static void print_strings (char *const *argv)
 {
-  int argc;
+  size_t argc;
 
   for (argc = 0; argv[argc] != NULL; ++argc)
     printf (\"\\t%%s\\n\", argv[argc]);
@@ -6455,7 +6458,7 @@ static void print_strings (char *const *argv)
 /*
 static void print_table (char const *const *argv)
 {
-  int i;
+  size_t i;
 
   for (i = 0; argv[i] != NULL; i += 2)
     printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
@@ -7089,7 +7092,7 @@ and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
         | RString _ -> pr "    char *r;\n"; "NULL"
         | RStringList _ | RHashtable _ ->
             pr "    char **r;\n";
-            pr "    int i;\n";
+            pr "    size_t i;\n";
             "NULL"
         | RStruct (_, typ) ->
             pr "    struct guestfs_%s *r;\n" typ; "NULL"
@@ -7485,9 +7488,10 @@ and generate_fish_cmds () =
 
       List.iter (
         function
-        | Device name | String name
-        | OptString name | FileIn name | FileOut name | Bool name
-        | Int name | Int64 name -> ()
+        | Device _ | String _
+        | OptString _ | Bool _
+        | Int _ | Int64 _
+        | FileIn _ | FileOut _ -> ()
         | Pathname name | Dev_or_Path name ->
             pr "  free (%s);\n" name
         | StringList name | DeviceList name ->
@@ -7635,7 +7639,7 @@ static const char *const commands[] = {
 static char *
 generator (const char *text, int state)
 {
-  static int index, len;
+  static size_t index, len;
   const char *name;
 
   if (!state) {
@@ -7919,7 +7923,7 @@ and generate_ocaml_c () =
 #include <caml/mlvalues.h>
 #include <caml/signals.h>
 
-#include <guestfs.h>
+#include \"guestfs.h\"
 
 #include \"guestfs_c.h\"
 
@@ -7932,7 +7936,7 @@ copy_table (char * const * argv)
 {
   CAMLparam0 ();
   CAMLlocal5 (rv, pairv, kv, vv, cons);
-  int i;
+  size_t i;
 
   rv = Val_int (0);
   for (i = 0; argv[i] != NULL; i += 2) {
@@ -8087,11 +8091,12 @@ copy_table (char * const * argv)
         | String n
         | FileIn n
         | FileOut n ->
-            pr "  const char *%s = String_val (%sv);\n" n n
+            (* Copy strings in case the GC moves them: RHBZ#604691 *)
+            pr "  char *%s = guestfs_safe_strdup (g, String_val (%sv));\n" n n
         | OptString n ->
-            pr "  const char *%s =\n" n;
-            pr "    %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
-              n n
+            pr "  char *%s =\n" n;
+            pr "    %sv != Val_int (0) ?" n;
+            pr "      guestfs_safe_strdup (g, String_val (Field (%sv, 0))) : NULL;\n" n
         | StringList n | DeviceList n ->
             pr "  char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
         | Bool n ->
@@ -8111,7 +8116,7 @@ copy_table (char * const * argv)
             pr "  const char *r;\n"; "NULL"
         | RString _ -> pr "  char *r;\n"; "NULL"
         | RStringList _ ->
-            pr "  int i;\n";
+            pr "  size_t i;\n";
             pr "  char **r;\n";
             "NULL"
         | RStruct (_, typ) ->
@@ -8119,7 +8124,7 @@ copy_table (char * const * argv)
         | RStructList (_, typ) ->
             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
         | RHashtable _ ->
-            pr "  int i;\n";
+            pr "  size_t i;\n";
             pr "  char **r;\n";
             "NULL"
         | RBufferOut _ ->
@@ -8134,13 +8139,15 @@ copy_table (char * const * argv)
       pr ";\n";
       pr "  caml_leave_blocking_section ();\n";
 
+      (* Free strings if we copied them above. *)
       List.iter (
         function
+        | Pathname n | Device n | Dev_or_Path n | String n | OptString n
+        | FileIn n | FileOut n ->
+            pr "  free (%s);\n" n
         | StringList n | DeviceList n ->
             pr "  ocaml_guestfs_free_strings (%s);\n" n;
-        | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
-        | Bool _ | Int _ | Int64 _
-        | FileIn _ | FileOut _ -> ()
+        | Bool _ | Int _ | Int64 _ -> ()
       ) (snd style);
 
       pr "  if (r == %s)\n" error_code;
@@ -8479,7 +8486,7 @@ DESTROY (g)
        | RStringList n | RHashtable n ->
            pr "PREINIT:\n";
            pr "      char **%s;\n" n;
-           pr "      int i, n;\n";
+           pr "      size_t i, n;\n";
            pr " PPCODE:\n";
            pr "      %s = guestfs_%s " n name;
            generate_c_call_args ~handle:"g" style;
@@ -8523,7 +8530,7 @@ DESTROY (g)
 and generate_perl_struct_list_code typ cols name style n do_cleanups =
   pr "PREINIT:\n";
   pr "      struct guestfs_%s_list *%s;\n" typ n;
-  pr "      int i;\n";
+  pr "      size_t i;\n";
   pr "      HV *hv;\n";
   pr " PPCODE:\n";
   pr "      %s = guestfs_%s " n name;
@@ -8777,6 +8784,12 @@ and generate_python_c () =
   pr "\
 #include <Python.h>
 
+#if PY_VERSION_HEX < 0x02050000
+typedef int Py_ssize_t;
+#define PY_SSIZE_T_MAX INT_MAX
+#define PY_SSIZE_T_MIN INT_MIN
+#endif
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <assert.h>
@@ -8808,7 +8821,7 @@ put_handle (guestfs_h *g)
 static char **
 get_string_list (PyObject *obj)
 {
-  int i, len;
+  size_t i, len;
   char **r;
 
   assert (obj);
@@ -8818,7 +8831,12 @@ get_string_list (PyObject *obj)
     return NULL;
   }
 
-  len = PyList_Size (obj);
+  Py_ssize_t slen = PyList_Size (obj);
+  if (slen == -1) {
+    PyErr_SetString (PyExc_RuntimeError, \"get_string_list: PyList_Size failure\");
+    return NULL;
+  }
+  len = (size_t) slen;
   r = malloc (sizeof (char *) * (len+1));
   if (r == NULL) {
     PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
@@ -8916,7 +8934,7 @@ py_guestfs_close (PyObject *self, PyObject *args)
     pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
     pr "{\n";
     pr "  PyObject *list;\n";
-    pr "  int i;\n";
+    pr "  size_t i;\n";
     pr "\n";
     pr "  list = PyList_New (%ss->len);\n" typ;
     pr "  for (i = 0; i < %ss->len; ++i)\n" typ;
@@ -9399,7 +9417,7 @@ static VALUE ruby_guestfs_close (VALUE gv)
             pr "  char **%s;\n" n;
             pr "  Check_Type (%sv, T_ARRAY);\n" n;
             pr "  {\n";
-            pr "    int i, len;\n";
+            pr "    size_t i, len;\n";
             pr "    len = RARRAY_LEN (%sv);\n" n;
             pr "    %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
               n;
@@ -9470,7 +9488,7 @@ static VALUE ruby_guestfs_close (VALUE gv)
            pr "  free (r);\n";
            pr "  return rv;\n";
        | RStringList _ ->
-           pr "  int i, len = 0;\n";
+           pr "  size_t i, len = 0;\n";
            pr "  for (i = 0; r[i] != NULL; ++i) len++;\n";
            pr "  VALUE rv = rb_ary_new2 (len);\n";
            pr "  for (i = 0; r[i] != NULL; ++i) {\n";
@@ -9487,7 +9505,7 @@ static VALUE ruby_guestfs_close (VALUE gv)
            generate_ruby_struct_list_code typ cols
        | RHashtable _ ->
            pr "  VALUE rv = rb_hash_new ();\n";
-           pr "  int i;\n";
+           pr "  size_t i;\n";
            pr "  for (i = 0; r[i] != NULL; i+=2) {\n";
            pr "    rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
            pr "    free (r[i]);\n";
@@ -9556,7 +9574,7 @@ and generate_ruby_struct_code typ cols =
 (* Ruby code to return a struct list. *)
 and generate_ruby_struct_list_code typ cols =
   pr "  VALUE rv = rb_ary_new2 (r->len);\n";
-  pr "  int i;\n";
+  pr "  size_t i;\n";
   pr "  for (i = 0; i < r->len; ++i) {\n";
   pr "    VALUE hv = rb_hash_new ();\n";
   List.iter (
@@ -9956,7 +9974,7 @@ Java_com_redhat_et_libguestfs_GuestFS__1close
                        | DeviceList _ -> true
                        | _ -> false) (snd style) in
       if needs_i then
-        pr "  int i;\n";
+        pr "  size_t i;\n";
 
       pr "\n";
 
@@ -10594,7 +10612,7 @@ namespace Guestfs
            pr "      return r != 0 ? true : false;\n"
        | RHashtable _ ->
            pr "      Hashtable rr = new Hashtable ();\n";
-           pr "      for (int i = 0; i < r.Length; i += 2)\n";
+           pr "      for (size_t i = 0; i < r.Length; i += 2)\n";
            pr "        rr.Add (r[i], r[i+1]);\n";
            pr "      return rr;\n"
        | RInt _ | RInt64 _ | RConstString _ | RConstOptString _
@@ -10631,7 +10649,7 @@ and generate_bindtests () =
 static void
 print_strings (char *const *argv)
 {
-  int argc;
+  size_t argc;
 
   printf (\"[\");
   for (argc = 0; argv[argc] != NULL; ++argc) {