diff --git a/lib/kernel/src/code.erl b/lib/kernel/src/code.erl index 54082f21b608..dc8fc44a6a36 100644 --- a/lib/kernel/src/code.erl +++ b/lib/kernel/src/code.erl @@ -1751,7 +1751,8 @@ file containing object code for `Module` and returns the absolute filename. which(Module) when is_atom(Module) -> case is_loaded(Module) of false -> - which(Module, get_path()); + File = atom_to_list(Module) ++ objfile_extension(), + where_is_file(File); {file, File} -> File end. @@ -1773,8 +1774,7 @@ locate application resource files. Filename :: file:filename(), Absname :: file:filename(). where_is_file(File) when is_list(File) -> - Path = get_path(), - where_is_file(Path, File). + call({where_is_file, File}). %% To avoid unnecessary work when looking at many modules, this also %% accepts pairs of directories and pre-fetched contents in the path diff --git a/lib/kernel/src/code_server.erl b/lib/kernel/src/code_server.erl index 7689acf12468..34ff7037d15c 100644 --- a/lib/kernel/src/code_server.erl +++ b/lib/kernel/src/code_server.erl @@ -302,6 +302,11 @@ handle_call({replace_path,Name,Dir,Control}, _From, handle_call(get_path, _From, S) -> {reply,[P || {P, _Cache} <- S#state.path],S}; +handle_call({where_is_file,File}, _From, + #state{path=Path,path_cache=Cache0}=S) -> + {Resp,Cache} = where_is_file(Path, File, Cache0), + {reply,Resp,S#state{path_cache=Cache}}; + handle_call(clear_cache, _From, S) -> {reply,ok,S#state{path_cache=#{}}}; @@ -1485,3 +1490,22 @@ archive_extension() -> to_list(X) when is_list(X) -> X; to_list(X) when is_atom(X) -> atom_to_list(X). + +where_is_file([], _File, Cache) -> + {non_existing, Cache}; +where_is_file([{Dir, nocache} | Tail], File, Cache) -> + Full = filename:append(Dir, File), + case erl_prim_loader:read_file_info(Full) of + {ok,_} -> + {Full, Cache}; + _Error -> + where_is_file(Tail, File, Cache) + end; +where_is_file([{Dir, CacheKey} | Tail], File, Cache) when is_integer(CacheKey) -> + case with_cache(CacheKey, Dir, File, Cache) of + {true, Cache1} -> + Full = filename:append(Dir, File), + {Full, Cache1}; + {false, Cache1} -> + where_is_file(Tail, File, Cache1) + end.