[PATCH 1/2] generator: add a RelativePathnameList parameter type
Mostly like StringList (so it can used in current StringList parameters), but checking client- and daemon-side that the elements are relative paths. --- generator/bindtests.ml | 3 ++- generator/c.ml | 29 ++++++++++++++++++++++++----- generator/csharp.ml | 4 ++-- generator/daemon.ml | 20 ++++++++++++++++++-- generator/erlang.ml | 2 +- generator/fish.ml | 10 ++++++---- generator/gobject.ml | 7 ++++--- generator/golang.ml | 9 ++++++--- generator/haskell.ml | 9 +++++---- generator/java.ml | 10 +++++----- generator/lua.ml | 6 +++--- generator/ocaml.ml | 7 ++++--- generator/perl.ml | 9 ++++++--- generator/php.ml | 13 ++++++++----- generator/python.ml | 13 +++++++------ generator/ruby.ml | 4 ++-- generator/tests_c_api.ml | 7 +++++-- generator/types.ml | 4 ++++ generator/utils.ml | 2 +- generator/xdr.ml | 3 ++- 20 files changed, 115 insertions(+), 56 deletions(-) diff --git a/generator/bindtests.ml b/generator/bindtests.ml index 0959704..1d9ea3e 100644 --- a/generator/bindtests.ml +++ b/generator/bindtests.ml @@ -163,7 +163,8 @@ fill_lvm_pv (guestfs_h *g, struct guestfs_lvm_pv *pv, size_t i) pr " fprintf (fp, \"\\n\");\n"; pr " }\n"; | OptString n -> pr " fprintf (fp, \"%%s\\n\", %s ? %s : \"null\");\n" n n - | StringList n | DeviceList n -> pr " print_strings (g, %s);\n" n + | StringList n | DeviceList n | RelativePathnameList n -> + pr " print_strings (g, %s);\n" n | Bool n -> pr " fprintf (fp, \"%%s\\n\", %s ? \"true\" : \"false\");\n" n | Int n -> pr " fprintf (fp, \"%%d\\n\", %s);\n" n | Int64 n -> pr " fprintf (fp, \"%%\" PRIi64 \"\\n\", %s);\n" n diff --git a/generator/c.ml b/generator/c.ml index 055b683..183bf94 100644 --- a/generator/c.ml +++ b/generator/c.ml @@ -131,7 +131,7 @@ let rec generate_prototype ?(extern = true) ?(static = false) pr "const mountable_t *%s" n else pr "const char *%s" n - | StringList n | DeviceList n -> + | StringList n | DeviceList n | RelativePathnameList n -> next (); pr "char *const *%s" n | Bool n -> next (); pr "int %s" n @@ -1252,7 +1252,8 @@ and generate_client_actions hash () = | DeviceList n | Key n | Pointer (_, n) - | GUID n -> + | GUID n + | RelativePathnameList n -> pr " if (%s == NULL) {\n" n; pr " error (g, \"%%s: %%s: parameter cannot be NULL\",\n"; pr " \"%s\", \"%s\");\n" c_name n; @@ -1355,6 +1356,23 @@ and generate_client_actions hash () = pr " }\n"; pr_newline := true + | RelativePathnameList n -> + pr " {\n"; + pr " size_t i;\n"; + pr " for (i = 0; %s[i] != NULL; ++i) {\n" n; + pr " if (%s[i][0] == '/') {\n" n; + pr " error (g, \"%%s: %%s: path '%%s' must be relative\",\n"; + pr " \"%s\", \"%s\", %s[i]);\n" c_name n n; + let errcode = + match errcode_of_ret ret with + | `CannotReturnError -> assert false + | (`ErrorIsMinusOne |`ErrorIsNULL) as e -> e in + pr " return %s;\n" (string_of_errcode errcode); + pr " }\n"; + pr " }\n"; + pr " }\n"; + pr_newline := true + (* not applicable *) | String _ | Device _ @@ -1383,7 +1401,7 @@ and generate_client_actions hash () = let needs_i = List.exists (function - | StringList _ | DeviceList _ -> true + | StringList _ | DeviceList _ | RelativePathnameList _ -> true | _ -> false) args || List.exists (function | OStringList _ -> true @@ -1419,7 +1437,8 @@ and generate_client_actions hash () = pr " else\n"; pr " fprintf (trace_buffer.fp, \" null\");\n" | StringList n - | DeviceList n -> (* string list *) + | DeviceList n + | RelativePathnameList n -> (* string list *) pr " fputc (' ', trace_buffer.fp);\n"; pr " fputc ('\"', trace_buffer.fp);\n"; pr " for (i = 0; %s[i]; ++i) {\n" n; @@ -1735,7 +1754,7 @@ and generate_client_actions hash () = pr " args.%s = (char *) %s;\n" n n | OptString n -> pr " args.%s = %s ? (char **) &%s : NULL;\n" n n n - | StringList n | DeviceList n -> + | StringList n | DeviceList n | RelativePathnameList n -> pr " args.%s.%s_val = (char **) %s;\n" n n n; pr " for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n; | Bool n -> diff --git a/generator/csharp.ml b/generator/csharp.ml index e2bd25b..59f7be9 100644 --- a/generator/csharp.ml +++ b/generator/csharp.ml @@ -195,7 +195,7 @@ namespace Guestfs | BufferIn n | GUID n -> pr ", [In] string %s" n - | StringList n | DeviceList n -> + | StringList n | DeviceList n | RelativePathnameList n -> pr ", [In] string[] %s" n | Bool n -> pr ", bool %s" n @@ -224,7 +224,7 @@ namespace Guestfs | BufferIn n | GUID n -> next (); pr "string %s" n - | StringList n | DeviceList n -> + | StringList n | DeviceList n | RelativePathnameList n -> next (); pr "string[] %s" n | Bool n -> next (); pr "bool %s" n diff --git a/generator/daemon.ml b/generator/daemon.ml index 1825de4..e6093a3 100644 --- a/generator/daemon.ml +++ b/generator/daemon.ml @@ -255,7 +255,7 @@ cleanup_free_mountable (mountable_t *mountable) | Mountable n | Mountable_or_Path n -> pr " CLEANUP_FREE_MOUNTABLE mountable_t %s\n" n; pr " = { .device = NULL, .volume = NULL };\n" - | StringList n -> + | StringList n | RelativePathnameList n -> pr " char **%s;\n" n | DeviceList n -> pr " CLEANUP_FREE_STRING_LIST char **%s = NULL;\n" n @@ -344,7 +344,23 @@ cleanup_free_mountable (mountable_t *mountable) n n (if is_filein then "cancel_receive ()" else ""); | String n | Key n | GUID n -> pr_args n | OptString n -> pr " %s = args.%s ? *args.%s : NULL;\n" n n n - | StringList n -> + | StringList n | RelativePathnameList n as arg -> + (match arg with + | RelativePathnameList n -> + pr " {\n"; + pr " size_t i;\n"; + pr " for (i = 0; i < args.%s.%s_len; ++i) {\n" n n; + pr " if (args.%s.%s_val[i][0] == '/') {\n" n n; + if is_filein then + pr " cancel_receive ();\n"; + pr " reply_with_error (\"%%s: path '%%s' must be relative\", __func__, args.%s.%s_val[i]);\n" + n n; + pr " goto done;\n"; + pr " }\n"; + pr " }\n"; + pr " }\n" + | _ -> () + ); pr " /* Ugly, but safe and avoids copying the strings. */\n"; pr " %s = realloc (args.%s.%s_val,\n" n n n; pr " sizeof (char *) * (args.%s.%s_len+1));\n" n n; diff --git a/generator/erlang.ml b/generator/erlang.ml index 5d4faaf..c09d97c 100644 --- a/generator/erlang.ml +++ b/generator/erlang.ml @@ -310,7 +310,7 @@ extern int64_t get_int64 (ETERM *term); pr " ETERM *%s_bin = erl_iolist_to_binary (ARG (%d));\n" n i; pr " const void *%s = ERL_BIN_PTR (%s_bin);\n" n n; pr " size_t %s_size = ERL_BIN_SIZE (%s_bin);\n" n n - | StringList n | DeviceList n -> + | StringList n | DeviceList n | RelativePathnameList n -> pr " CLEANUP_FREE_STRING_LIST char **%s = get_string_list (ARG (%d));\n" n i | Bool n -> pr " int %s = get_bool (ARG (%d));\n" n i diff --git a/generator/fish.ml b/generator/fish.ml index 6f68e65..cfbec2a 100644 --- a/generator/fish.ml +++ b/generator/fish.ml @@ -376,7 +376,8 @@ Guestfish will prompt for these separately." | BufferIn n -> pr " const char *%s;\n" n; pr " size_t %s_size;\n" n - | StringList n | DeviceList n -> pr " char **%s;\n" n + | StringList n | DeviceList n | RelativePathnameList n -> + pr " char **%s;\n" n | Bool n -> pr " int %s;\n" n | Int n -> pr " int %s;\n" n | Int64 n -> pr " int64_t %s;\n" n @@ -464,7 +465,7 @@ Guestfish will prompt for these separately." | FileOut name -> pr " %s = file_out (argv[i++]);\n" name; pr " if (%s == NULL) goto out_%s;\n" name name - | StringList name | DeviceList name -> + | StringList name | DeviceList name | RelativePathnameList name -> pr " %s = parse_string_list (argv[i++]);\n" name; pr " if (%s == NULL) goto out_%s;\n" name name | Key name -> @@ -678,7 +679,7 @@ Guestfish will prompt for these separately." | FileIn name -> pr " free_file_in (%s);\n" name; pr " out_%s:\n" name - | StringList name | DeviceList name -> + | StringList name | DeviceList name | RelativePathnameList name -> pr " guestfs_int_free_string_list (%s);\n" name; pr " out_%s:\n" name | Pointer _ -> assert false @@ -917,7 +918,8 @@ and generate_fish_actions_pod () = | GUID n -> pr " %s" n | OptString n -> pr " %s" n - | StringList n | DeviceList n -> pr " '%s ...'" n + | StringList n | DeviceList n | RelativePathnameList n -> + pr " '%s ...'" n | Bool _ -> pr " true|false" | Int n -> pr " %s" n | Int64 n -> pr " %s" n diff --git a/generator/gobject.ml b/generator/gobject.ml index 8d5ac06..15f214b 100644 --- a/generator/gobject.ml +++ b/generator/gobject.ml @@ -85,7 +85,8 @@ let generate_gobject_proto name ?(single_line = true) | GUID n -> pr "const gchar *%s" n | StringList n - | DeviceList n -> + | DeviceList n + | RelativePathnameList n -> pr "gchar *const *%s" n | BufferIn n -> pr "const guint8 *%s, gsize %s_size" n n @@ -1052,7 +1053,7 @@ guestfs_session_close (GuestfsSession *session, GError **err) pr " (transfer none) (type filename):" | StringList _ -> pr " (transfer none) (array zero-terminated=1) (element-type utf8): an array of strings" - | DeviceList _ -> + | DeviceList _ | RelativePathnameList _ -> pr " (transfer none) (array zero-terminated=1) (element-type filename): an array of strings" | BufferIn n -> pr " (transfer none) (array length=%s_size) (element-type guint8): an array of binary data\n" n; @@ -1211,7 +1212,7 @@ guestfs_session_close (GuestfsSession *session, GError **err) | Pathname n | Dev_or_Path n | Mountable_or_Path n | OptString n | StringList n | DeviceList n | Key n | FileIn n | FileOut n - | GUID n -> + | GUID n | RelativePathnameList n -> pr "%s" n | Pointer (_, n) -> pr "%s" n diff --git a/generator/golang.ml b/generator/golang.ml index b4b2482..cfc5b5b 100644 --- a/generator/golang.ml +++ b/generator/golang.ml @@ -315,7 +315,8 @@ func return_hashtable (argv **C.char) map[string]string { | GUID n -> pr "%s string" n | OptString n -> pr "%s *string" n | StringList n - | DeviceList n -> pr "%s []string" n + | DeviceList n + | RelativePathnameList n -> pr "%s []string" n | BufferIn n -> pr "%s []byte" n | Pointer (_, n) -> pr "%s int64" n ) args; @@ -380,7 +381,8 @@ func return_hashtable (argv **C.char) map[string]string { pr " defer C.free (unsafe.Pointer (c_%s))\n" n; pr " }\n" | StringList n - | DeviceList n -> + | DeviceList n + | RelativePathnameList n -> pr "\n"; pr " c_%s := arg_string_list (%s)\n" n n; pr " defer free_string_list (c_%s)\n" n @@ -455,7 +457,8 @@ func return_hashtable (argv **C.char) map[string]string { | FileIn n | FileOut n | GUID n -> pr "c_%s" n | StringList n - | DeviceList n -> pr "c_%s" n + | DeviceList n + | RelativePathnameList n -> pr "c_%s" n | BufferIn n -> pr "c_%s, C.size_t (len (%s))" n n | Pointer _ -> pr "nil" ) args; diff --git a/generator/haskell.ml b/generator/haskell.ml index 96682e6..7e3e0c2 100644 --- a/generator/haskell.ml +++ b/generator/haskell.ml @@ -147,7 +147,8 @@ assocListOfHashtable (a:b:rest) = (a,b) : assocListOfHashtable rest | BufferIn n -> pr "withCStringLen %s $ \\(%s, %s_size) -> " n n n | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n - | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n + | StringList n | DeviceList n | RelativePathnameList n -> + pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n | Bool _ | Int _ | Int64 _ | Pointer _ -> () ) args; (* Convert integer arguments. *) @@ -161,7 +162,7 @@ assocListOfHashtable (a:b:rest) = (a,b) : assocListOfHashtable rest | Pathname n | Device n | Mountable n | Dev_or_Path n | Mountable_or_Path n | String n | OptString n - | StringList n | DeviceList n + | StringList n | DeviceList n | RelativePathnameList n | Key n | GUID n -> n | BufferIn n -> sprintf "%s (fromIntegral %s_size)" n n ) args in @@ -224,7 +225,7 @@ and generate_haskell_prototype ~handle ?(hs = false) (ret, args, optargs) = pr "CString -> CInt" | OptString _ -> pr "CString" - | StringList _ | DeviceList _ -> + | StringList _ | DeviceList _ | RelativePathnameList _ -> pr "Ptr CString" | Bool _ -> pr "CInt" | Int _ -> pr "CInt" @@ -267,7 +268,7 @@ and generate_haskell_prototype ~handle ?(hs = false) (ret, args, optargs) = pr "String" | OptString _ -> pr "Maybe String" - | StringList _ | DeviceList _ -> + | StringList _ | DeviceList _ | RelativePathnameList _ -> pr "[String]" | Bool _ -> pr "Bool" | Int _ -> pr "Int" diff --git a/generator/java.ml b/generator/java.ml index 4c89197..81fbf9b 100644 --- a/generator/java.ml +++ b/generator/java.ml @@ -485,7 +485,7 @@ and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false) pr "String %s" n | BufferIn n -> pr "byte[] %s" n - | StringList n | DeviceList n -> + | StringList n | DeviceList n | RelativePathnameList n -> pr "String[] %s" n | Bool n -> pr "boolean %s" n @@ -846,7 +846,7 @@ get_all_event_callbacks (guestfs_h *g, size_t *len_rtn) pr ", jstring j%s" n | BufferIn n -> pr ", jbyteArray j%s" n - | StringList n | DeviceList n -> + | StringList n | DeviceList n | RelativePathnameList n -> pr ", jobjectArray j%s" n | Bool n -> pr ", jboolean j%s" n @@ -917,7 +917,7 @@ get_all_event_callbacks (guestfs_h *g, size_t *len_rtn) | BufferIn n -> pr " char *%s;\n" n; pr " size_t %s_size;\n" n - | StringList n | DeviceList n -> + | StringList n | DeviceList n | RelativePathnameList n -> pr " size_t %s_len;\n" n; pr " char **%s;\n" n | Bool n @@ -979,7 +979,7 @@ get_all_event_callbacks (guestfs_h *g, size_t *len_rtn) | BufferIn n -> pr " %s = (char *) (*env)->GetByteArrayElements (env, j%s, NULL);\n" n n; pr " %s_size = (*env)->GetArrayLength (env, j%s);\n" n n - | StringList n | DeviceList n -> + | StringList n | DeviceList n | RelativePathnameList n -> pr " %s_len = (*env)->GetArrayLength (env, j%s);\n" n n; pr " %s = guestfs_int_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n; pr " for (i = 0; i < %s_len; ++i) {\n" n; @@ -1044,7 +1044,7 @@ get_all_event_callbacks (guestfs_h *g, size_t *len_rtn) pr " (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n | BufferIn n -> pr " (*env)->ReleaseByteArrayElements (env, j%s, (jbyte *) %s, 0);\n" n n - | StringList n | DeviceList n -> + | StringList n | DeviceList n | RelativePathnameList n -> pr " for (i = 0; i < %s_len; ++i) {\n" n; pr " jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n" n; diff --git a/generator/lua.ml b/generator/lua.ml index 630d805..ea47739 100644 --- a/generator/lua.ml +++ b/generator/lua.ml @@ -474,7 +474,7 @@ guestfs_lua_delete_event_callback (lua_State *L) pr " size_t %s_size;\n" n; | OptString n -> pr " const char *%s;\n" n; - | StringList n | DeviceList n -> + | StringList n | DeviceList n | RelativePathnameList n -> pr " char **%s;\n" n | Bool n -> pr " int %s;\n" n | Int n -> pr " int %s;\n" n @@ -504,7 +504,7 @@ guestfs_lua_delete_event_callback (lua_State *L) pr " %s = luaL_checklstring (L, %d, &%s_size);\n" n i n | OptString n -> pr " %s = luaL_optstring (L, %d, NULL);\n" n i - | StringList n | DeviceList n -> + | StringList n | DeviceList n | RelativePathnameList n -> pr " %s = get_string_list (L, %d);\n" n i | Bool n -> pr " %s = lua_toboolean (L, %d);\n" n i @@ -564,7 +564,7 @@ guestfs_lua_delete_event_callback (lua_State *L) | BufferIn _ | OptString _ | Bool _ | Int _ | Int64 _ | Pointer _ | GUID _ -> () - | StringList n | DeviceList n -> + | StringList n | DeviceList n | RelativePathnameList n -> pr " free (%s);\n" n ) args; List.iter ( diff --git a/generator/ocaml.ml b/generator/ocaml.ml index 5d92fcb..d8ab3b1 100644 --- a/generator/ocaml.ml +++ b/generator/ocaml.ml @@ -600,7 +600,7 @@ copy_table (char * const * argv) | BufferIn n -> pr " size_t %s_size = caml_string_length (%sv);\n" n n; pr " char *%s = guestfs_int_safe_memdup (g, String_val (%sv), %s_size);\n" n n n - | StringList n | DeviceList n -> + | StringList n | DeviceList n | RelativePathnameList n -> pr " char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n | Bool n -> pr " int %s = Bool_val (%sv);\n" n n @@ -677,7 +677,7 @@ copy_table (char * const * argv) | OptString n | FileIn n | FileOut n | BufferIn n | Key n | GUID n -> pr " free (%s);\n" n - | StringList n | DeviceList n -> + | StringList n | DeviceList n | RelativePathnameList n -> pr " guestfs_int_free_string_list (%s);\n" n; | Bool _ | Int _ | Int64 _ | Pointer _ -> () ) args; @@ -850,7 +850,8 @@ and generate_ocaml_function_type ?(extra_unit = false) (ret, args, optargs) = | FileIn _ | FileOut _ | BufferIn _ | Key _ | GUID _ -> pr "string -> " | OptString _ -> pr "string option -> " - | StringList _ | DeviceList _ -> pr "string array -> " + | StringList _ | DeviceList _ | RelativePathnameList _ -> + pr "string array -> " | Bool _ -> pr "bool -> " | Int _ -> pr "int -> " | Int64 _ | Pointer _ -> pr "int64 -> " diff --git a/generator/perl.ml b/generator/perl.ml index dcd180f..f1d5d6d 100644 --- a/generator/perl.ml +++ b/generator/perl.ml @@ -365,7 +365,8 @@ PREINIT: * to add 1 to the ST(x) operator. *) pr " char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1) - | StringList n | DeviceList n -> pr " char **%s;\n" n + | StringList n | DeviceList n | RelativePathnameList n -> + pr " char **%s;\n" n | Bool n -> pr " int %s;\n" n | Int n -> pr " int %s;\n" n | Int64 n -> pr " int64_t %s;\n" n @@ -510,7 +511,8 @@ PREINIT: | OptString _ | Bool _ | Int _ | Int64 _ | FileIn _ | FileOut _ | BufferIn _ | Key _ | Pointer _ | GUID _ -> () - | StringList n | DeviceList n -> pr " free (%s);\n" n + | StringList n | DeviceList n | RelativePathnameList n -> + pr " free (%s);\n" n ) args; (* Check return value for errors and return it if necessary. *) @@ -955,6 +957,7 @@ errnos: | Int n -> pr "[ '%s', 'int', %d ]" n i | Int64 n -> pr "[ '%s', 'int64', %d ]" n i | Pointer (t, n) -> pr "[ '%s', 'pointer(%s)', %d ]" n t i + | RelativePathnameList n -> pr "[ '%s', 'string(path) list', %d ]" n i in pr " args => [\n"; iteri (fun i arg -> @@ -1113,7 +1116,7 @@ and generate_perl_prototype name (ret, args, optargs) = | OptString n | Bool n | Int n | Int64 n | FileIn n | FileOut n | BufferIn n | Key n | Pointer (_, n) | GUID n -> pr "$%s" n - | StringList n | DeviceList n -> + | StringList n | DeviceList n | RelativePathnameList n -> pr "\\@%s" n ) args; List.iter ( diff --git a/generator/php.ml b/generator/php.ml index b49bf60..82e0cd4 100644 --- a/generator/php.ml +++ b/generator/php.ml @@ -240,7 +240,8 @@ PHP_FUNCTION (guestfs_last_error) pr " char *%s = NULL;\n" n; pr " int %s_size;\n" n | StringList n - | DeviceList n -> + | DeviceList n + | RelativePathnameList n -> pr " zval *z_%s;\n" n; pr " char **%s;\n" n; | Bool n -> @@ -284,7 +285,7 @@ PHP_FUNCTION (guestfs_last_error) | FileIn n | FileOut n | BufferIn n | Key n | GUID n -> "s" | OptString n -> "s!" - | StringList n | DeviceList n -> "a" + | StringList n | DeviceList n | RelativePathnameList n -> "a" | Bool n -> "b" | Int n | Int64 n -> "l" | Pointer _ -> "" @@ -319,7 +320,7 @@ PHP_FUNCTION (guestfs_last_error) | FileIn n | FileOut n | BufferIn n | Key n | OptString n | GUID n -> pr ", &%s, &%s_size" n n - | StringList n | DeviceList n -> + | StringList n | DeviceList n | RelativePathnameList n -> pr ", &z_%s" n | Bool n -> pr ", &%s" n @@ -372,7 +373,8 @@ PHP_FUNCTION (guestfs_last_error) pr "\n" | BufferIn n -> () | StringList n - | DeviceList n -> + | DeviceList n + | RelativePathnameList n -> pr " %s = get_stringlist (z_%s);\n" n n; pr "\n" | Bool _ | Int _ | Int64 _ -> () @@ -453,7 +455,8 @@ PHP_FUNCTION (guestfs_last_error) | OptString n | GUID n -> () | BufferIn n -> () | StringList n - | DeviceList n -> + | DeviceList n + | RelativePathnameList n -> pr " guestfs_efree_stringlist (%s);\n" n; pr "\n" | Bool _ | Int _ | Int64 _ | Pointer _ -> () diff --git a/generator/python.ml b/generator/python.ml index 1e043fc..b8329a5 100644 --- a/generator/python.ml +++ b/generator/python.ml @@ -292,7 +292,7 @@ put_table (char * const * const argv) | BufferIn n -> pr " const char *%s;\n" n; pr " Py_ssize_t %s_size;\n" n - | StringList n | DeviceList n -> + | StringList n | DeviceList n | RelativePathnameList n -> pr " PyObject *py_%s;\n" n; pr " char **%s = NULL;\n" n | Bool n -> pr " int %s;\n" n @@ -326,7 +326,7 @@ put_table (char * const * const argv) | Dev_or_Path _ | Mountable_or_Path _ | String _ | Key _ | FileIn _ | FileOut _ | GUID _ -> pr "s" | OptString _ -> pr "z" - | StringList _ | DeviceList _ -> pr "O" + | StringList _ | DeviceList _ | RelativePathnameList _ -> pr "O" | Bool _ -> pr "i" (* XXX Python has booleans? *) | Int _ -> pr "i" | Int64 _ -> @@ -349,7 +349,8 @@ put_table (char * const * const argv) | Dev_or_Path n | Mountable_or_Path n | String n | Key n | FileIn n | FileOut n | GUID n -> pr ", &%s" n | OptString n -> pr ", &%s" n - | StringList n | DeviceList n -> pr ", &py_%s" n + | StringList n | DeviceList n | RelativePathnameList n -> + pr ", &py_%s" n | Bool n -> pr ", &%s" n | Int n -> pr ", &%s" n | Int64 n -> pr ", &%s" n @@ -372,7 +373,7 @@ put_table (char * const * const argv) | Dev_or_Path _ | Mountable_or_Path _ | String _ | Key _ | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ | BufferIn _ | GUID _ -> () - | StringList n | DeviceList n -> + | StringList n | DeviceList n | RelativePathnameList n -> pr " %s = get_string_list (py_%s);\n" n n; pr " if (!%s) goto out;\n" n | Pointer (_, n) -> @@ -522,7 +523,7 @@ put_table (char * const * const argv) | Dev_or_Path _ | Mountable_or_Path _ | String _ | Key _ | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ | BufferIn _ | Pointer _ | GUID _ -> () - | StringList n | DeviceList n -> + | StringList n | DeviceList n | RelativePathnameList n -> pr " free (%s);\n" n ) args; @@ -829,7 +830,7 @@ class GuestFS(object): | Dev_or_Path _ | Mountable_or_Path _ | String _ | Key _ | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ | BufferIn _ | GUID _ -> () - | StringList n | DeviceList n -> + | StringList n | DeviceList n | RelativePathnameList n -> pr " %s = list (%s)\n" n n | Pointer (_, n) -> pr " %s = %s.c_pointer()\n" n n diff --git a/generator/ruby.ml b/generator/ruby.ml index cb187b0..5e22ed0 100644 --- a/generator/ruby.ml +++ b/generator/ruby.ml @@ -582,7 +582,7 @@ get_all_event_callbacks (guestfs_h *g, size_t *len_rtn) pr " size_t %s_size = RSTRING_LEN (%sv);\n" n n | OptString n -> pr " const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n - | StringList n | DeviceList n -> + | StringList n | DeviceList n | RelativePathnameList n -> pr " char **%s;\n" n; pr " Check_Type (%sv, T_ARRAY);\n" n; pr " {\n"; @@ -677,7 +677,7 @@ get_all_event_callbacks (guestfs_h *g, size_t *len_rtn) | Dev_or_Path _ | Mountable_or_Path _ | String _ | Key _ | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ | BufferIn _ | Pointer _ | GUID _ -> () - | StringList n | DeviceList n -> + | StringList n | DeviceList n | RelativePathnameList n -> pr " free (%s);\n" n ) args; diff --git a/generator/tests_c_api.ml b/generator/tests_c_api.ml index 1522eff..c5af42f 100644 --- a/generator/tests_c_api.ml +++ b/generator/tests_c_api.ml @@ -419,7 +419,8 @@ and generate_test_command_call ?(expect_error = false) ?test ?ret test_name cmd= | DeviceList _, "", sym -> pr " const char *const %s[1] = { NULL };\n" sym | StringList _, arg, sym - | DeviceList _, arg, sym -> + | DeviceList _, arg, sym + | RelativePathnameList _, arg, sym -> let strs = string_split " " arg in iteri ( fun i str -> @@ -527,7 +528,9 @@ and generate_test_command_call ?(expect_error = false) ?test ?ret test_name cmd= | GUID _, _, sym -> pr ", %s" sym | BufferIn _, _, sym -> pr ", %s, %s_size" sym sym | FileOut _, arg, _ -> pr ", \"%s\"" (c_quote arg) - | StringList _, _, sym | DeviceList _, _, sym -> pr ", (char **) %s" sym + | StringList _, _, sym | DeviceList _, _, sym + | RelativePathnameList _, _, sym -> + pr ", (char **) %s" sym | Int _, arg, _ -> let i = try int_of_string arg diff --git a/generator/types.ml b/generator/types.ml index 83a6a98..156df3b 100644 --- a/generator/types.ml +++ b/generator/types.ml @@ -190,6 +190,10 @@ and argt = * guestfs_int_validate_guid. *) | GUID of string + (* List of file names, where the list cannot be NULL, and each + * filename cannot be NULL, empty, or an absolute path. + *) + | RelativePathnameList of string and optargs = optargt list diff --git a/generator/utils.ml b/generator/utils.ml index 1b00ce5..5b97b2b 100644 --- a/generator/utils.ml +++ b/generator/utils.ml @@ -254,7 +254,7 @@ let name_of_argt = function | Mountable_or_Path n | String n | OptString n | StringList n | DeviceList n | Bool n | Int n | Int64 n | FileIn n | FileOut n | BufferIn n | Key n | Pointer (_, n) - | GUID n -> n + | GUID n | RelativePathnameList n -> n let name_of_optargt = function | OBool n | OInt n | OInt64 n | OString n | OStringList n -> n diff --git a/generator/xdr.ml b/generator/xdr.ml index 37a52b7..aef5c1e 100644 --- a/generator/xdr.ml +++ b/generator/xdr.ml @@ -115,7 +115,8 @@ let generate_xdr () = | Key n | GUID n -> pr " string %s<>;\n" n | OptString n -> pr " guestfs_str *%s;\n" n - | StringList n | DeviceList n -> pr " guestfs_str %s<>;\n" n + | StringList n | DeviceList n | RelativePathnameList n -> + pr " guestfs_str %s<>;\n" n | Bool n -> pr " bool %s;\n" n | Int n -> pr " int %s;\n" n | Int64 n -> pr " int64_t %s;\n" n -- 2.1.0
Use RelativePathnameList as type for lists of relative paths, as used in some listing-alike APIs. This way we can ensure absolute paths in those lists are rejects outright. As a consequence, test-big-dirs.pl does not need to prepend the directory name anymore before calling listing-alike APIs: previously they didn't fail, but the returned lists contained only invalid elements (and only their size was checked). --- generator/actions.ml | 14 +++++++------- tests/bigdirs/test-big-dirs.pl | 1 - 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/generator/actions.ml b/generator/actions.ml index 274ef3f..a6de484 100644 --- a/generator/actions.ml +++ b/generator/actions.ml @@ -2655,7 +2655,7 @@ See also C<guestfs_write>." }; { defaults with name = "lstatlist"; added = (1, 0, 77); - style = RStructList ("statbufs", "stat"), [Pathname "path"; StringList "names"], []; + style = RStructList ("statbufs", "stat"), [Pathname "path"; RelativePathnameList "names"], []; deprecated_by = Some "lstatnslist"; shortdesc = "lstat on multiple files"; longdesc = "\ @@ -2675,7 +2675,7 @@ for getting extended attributes." }; { defaults with name = "lstatnslist"; added = (1, 27, 53); - style = RStructList ("statbufs", "statns"), [Pathname "path"; StringList "names"], []; + style = RStructList ("statbufs", "statns"), [Pathname "path"; RelativePathnameList "names"], []; shortdesc = "lstat on multiple files"; longdesc = "\ This call allows you to perform the C<guestfs_lstatns> operation @@ -2694,7 +2694,7 @@ for getting extended attributes." }; { defaults with name = "lxattrlist"; added = (1, 0, 77); - style = RStructList ("xattrs", "xattr"), [Pathname "path"; StringList "names"], []; + style = RStructList ("xattrs", "xattr"), [Pathname "path"; RelativePathnameList "names"], []; optional = Some "linuxxattrs"; shortdesc = "lgetxattr on multiple files"; longdesc = "\ @@ -2719,7 +2719,7 @@ for getting standard stats." }; { defaults with name = "readlinklist"; added = (1, 0, 77); - style = RStringList "links", [Pathname "path"; StringList "names"], []; + style = RStringList "links", [Pathname "path"; RelativePathnameList "names"], []; shortdesc = "readlink on multiple files"; longdesc = "\ This call allows you to do a C<readlink> operation @@ -7703,7 +7703,7 @@ yourself (Augeas support makes this relatively easy)." }; { defaults with name = "internal_lxattrlist"; added = (1, 19, 32); - style = RStructList ("xattrs", "xattr"), [Pathname "path"; StringList "names"], []; + style = RStructList ("xattrs", "xattr"), [Pathname "path"; RelativePathnameList "names"], []; proc_nr = Some 205; visibility = VInternal; optional = Some "linuxxattrs"; @@ -7733,7 +7733,7 @@ into smaller groups of names." }; { defaults with name = "internal_readlinklist"; added = (1, 19, 32); - style = RStringList "links", [Pathname "path"; StringList "names"], []; + style = RStringList "links", [Pathname "path"; RelativePathnameList "names"], []; proc_nr = Some 206; visibility = VInternal; shortdesc = "readlink on multiple files"; @@ -12220,7 +12220,7 @@ This is the same as the L<lstat(2)> system call." }; { defaults with name = "internal_lstatnslist"; added = (1, 27, 53); - style = RStructList ("statbufs", "statns"), [Pathname "path"; StringList "names"], []; + style = RStructList ("statbufs", "statns"), [Pathname "path"; RelativePathnameList "names"], []; proc_nr = Some 423; visibility = VInternal; shortdesc = "lstat on multiple files"; diff --git a/tests/bigdirs/test-big-dirs.pl b/tests/bigdirs/test-big-dirs.pl index 40038b7..5bcc71c 100755 --- a/tests/bigdirs/test-big-dirs.pl +++ b/tests/bigdirs/test-big-dirs.pl @@ -63,7 +63,6 @@ for (my $i = 0; $i < $nr_files; ++$i) { # Check that lstatlist, lxattrlist and readlinklist return the # expected number of entries. my @a; -@filenames = map { "/dir/$_" } @filenames; @a = $g->lstatlist ("/dir", \@filenames); die unless @a == $nr_files; -- 2.1.0
On Tue, Oct 20, 2015 at 01:59:10PM +0200, Pino Toscano wrote:
Use RelativePathnameList as type for lists of relative paths, as used in some listing-alike APIs. This way we can ensure absolute paths in those lists are rejects outright.
As a consequence, test-big-dirs.pl does not need to prepend the directory name anymore before calling listing-alike APIs: previously they didn't fail, but the returned lists contained only invalid elements (and only their size was checked).
Are these all relative pathnames, or are they in fact just filenames without any path at all. That is to say: is "foo/bar" permitted, or just "bar"? Rich. -- Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones Read my programming and virtualization blog: http://rwmj.wordpress.com virt-p2v converts physical machines to virtual machines. Boot with a live CD or over the network (PXE) and turn machines into KVM guests. http://libguestfs.org/virt-v2v
On Tuesday 20 October 2015 14:43:53 Richard W.M. Jones wrote:
On Tue, Oct 20, 2015 at 01:59:10PM +0200, Pino Toscano wrote:
Use RelativePathnameList as type for lists of relative paths, as used in some listing-alike APIs. This way we can ensure absolute paths in those lists are rejects outright.
As a consequence, test-big-dirs.pl does not need to prepend the directory name anymore before calling listing-alike APIs: previously they didn't fail, but the returned lists contained only invalid elements (and only their size was checked).
Are these all relative pathnames, or are they in fact just filenames without any path at all. That is to say: is "foo/bar" permitted, or just "bar"?
At least with *lstat*list and *readlinklist functions, the file names are considered as relative wrt the path specified, as they are resolved against the file descriptor of the directory. In case of *lxattrlist, the absolute path+name for each is built and used as path within the guest. So yes, "bar", "foo/bar", and "../bar" too, should work. -- Pino Toscano
On Tue, Oct 20, 2015 at 03:50:31PM +0200, Pino Toscano wrote:
On Tuesday 20 October 2015 14:43:53 Richard W.M. Jones wrote:
On Tue, Oct 20, 2015 at 01:59:10PM +0200, Pino Toscano wrote:
Use RelativePathnameList as type for lists of relative paths, as used in some listing-alike APIs. This way we can ensure absolute paths in those lists are rejects outright.
As a consequence, test-big-dirs.pl does not need to prepend the directory name anymore before calling listing-alike APIs: previously they didn't fail, but the returned lists contained only invalid elements (and only their size was checked).
Are these all relative pathnames, or are they in fact just filenames without any path at all. That is to say: is "foo/bar" permitted, or just "bar"?
At least with *lstat*list and *readlinklist functions, the file names are considered as relative wrt the path specified, as they are resolved against the file descriptor of the directory.
In case of *lxattrlist, the absolute path+name for each is built and used as path within the guest.
So yes, "bar", "foo/bar", and "../bar" too, should work.
I think I really meant -- is it a caller bug if the parameter contains a slash in it? All the *list functions were really intended as optimizations for fuse/guestmount, and IIRC it was intended that only filenames (not even relative paths) be used there. Rich. -- Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones Read my programming and virtualization blog: http://rwmj.wordpress.com virt-builder quickly builds VMs from scratch http://libguestfs.org/virt-builder.1.html
On Tuesday 20 October 2015 15:22:22 Richard W.M. Jones wrote:
On Tue, Oct 20, 2015 at 03:50:31PM +0200, Pino Toscano wrote:
On Tuesday 20 October 2015 14:43:53 Richard W.M. Jones wrote:
On Tue, Oct 20, 2015 at 01:59:10PM +0200, Pino Toscano wrote:
Use RelativePathnameList as type for lists of relative paths, as used in some listing-alike APIs. This way we can ensure absolute paths in those lists are rejects outright.
As a consequence, test-big-dirs.pl does not need to prepend the directory name anymore before calling listing-alike APIs: previously they didn't fail, but the returned lists contained only invalid elements (and only their size was checked).
Are these all relative pathnames, or are they in fact just filenames without any path at all. That is to say: is "foo/bar" permitted, or just "bar"?
At least with *lstat*list and *readlinklist functions, the file names are considered as relative wrt the path specified, as they are resolved against the file descriptor of the directory.
In case of *lxattrlist, the absolute path+name for each is built and used as path within the guest.
So yes, "bar", "foo/bar", and "../bar" too, should work.
I think I really meant -- is it a caller bug if the parameter contains a slash in it?
I don't know that :) I mean, considering even our code (see my change in test-big-dirs.pl) was passing more than just a filename in the specified path, then I thought relative filenames were somehow intended, and thus I just rejected absolute ones. I'm open to both positions though, either what I proposed in the patches or just reject any file name not in the current directory.
All the *list functions were really intended as optimizations for fuse/guestmount, and IIRC it was intended that only filenames (not even relative paths) be used there.
They are used also in diff & ls nowadays (still with filenames only though). -- Pino Toscano
On Tue, Oct 20, 2015 at 06:17:59PM +0200, Pino Toscano wrote:
I don't know that :) I mean, considering even our code (see my change in test-big-dirs.pl) was passing more than just a filename in the specified path, then I thought relative filenames were somehow intended, and thus I just rejected absolute ones.
I'm open to both positions though, either what I proposed in the patches or just reject any file name not in the current directory.
I think reject any filename which contains a slash char. Rich. -- Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones Read my programming and virtualization blog: http://rwmj.wordpress.com virt-df lists disk usage of guests without needing to install any software inside the virtual machine. Supports Linux and Windows. http://people.redhat.com/~rjones/virt-df/
On Tue, Oct 20, 2015 at 01:59:10PM +0200, Pino Toscano wrote:
diff --git a/tests/bigdirs/test-big-dirs.pl b/tests/bigdirs/test-big-dirs.pl index 40038b7..5bcc71c 100755 --- a/tests/bigdirs/test-big-dirs.pl +++ b/tests/bigdirs/test-big-dirs.pl @@ -63,7 +63,6 @@ for (my $i = 0; $i < $nr_files; ++$i) { # Check that lstatlist, lxattrlist and readlinklist return the # expected number of entries. my @a; -@filenames = map { "/dir/$_" } @filenames;
Yup, I'm sure that line was completely bogus, so tightening up validation of the *list parameters would be a good thing. Rich.
@a = $g->lstatlist ("/dir", \@filenames); die unless @a == $nr_files; -- 2.1.0
_______________________________________________ Libguestfs mailing list Libguestfs@redhat.com https://www.redhat.com/mailman/listinfo/libguestfs
-- Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones Read my programming and virtualization blog: http://rwmj.wordpress.com virt-top is 'top' for virtual machines. Tiny program with many powerful monitoring features, net stats, disk stats, logging, etc. http://people.redhat.com/~rjones/virt-top
participants (2)
-
Pino Toscano -
Richard W.M. Jones