aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--erts/preloaded/src/erl_prim_loader.erl201
-rw-r--r--erts/preloaded/src/prim_zip.erl57
-rw-r--r--lib/kernel/src/code.erl24
-rw-r--r--lib/kernel/src/code_server.erl14
-rw-r--r--lib/kernel/test/erl_prim_loader_SUITE.erl74
-rw-r--r--lib/stdlib/src/escript.erl13
6 files changed, 251 insertions, 132 deletions
diff --git a/erts/preloaded/src/erl_prim_loader.erl b/erts/preloaded/src/erl_prim_loader.erl
index 399c2bb55d..c0785083de 100644
--- a/erts/preloaded/src/erl_prim_loader.erl
+++ b/erts/preloaded/src/erl_prim_loader.erl
@@ -1,19 +1,19 @@
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 1996-2010. All Rights Reserved.
+%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
%% compliance with the License. You should have received a copy of the
%% Erlang Public License along with this software. If not, it can be
%% retrieved online at http://www.erlang.org/.
-%%
+%%
%% Software distributed under the License is distributed on an "AS IS"
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
%% the License for the specific language governing rights and limitations
%% under the License.
-%%
+%%
%% %CopyrightEnd%
%%
@@ -49,7 +49,7 @@
prim_read_file_info/2, prim_get_cwd/2]).
%% Used by escript and code
--export([set_primary_archive/2, release_archives/0]).
+-export([set_primary_archive/3, release_archives/0]).
%% Internal function. Exported to avoid dialyzer warnings
-export([concat/1]).
@@ -220,14 +220,15 @@ get_cwd(Drive) ->
check_file_result(get_cwd, Drive, request({get_cwd,[Drive]})).
-spec set_primary_archive(File :: string() | 'undefined',
- ArchiveBin :: binary() | 'undefined')
- -> {ok, [string()]} | {error,_}.
+ ArchiveBin :: binary() | 'undefined',
+ FileInfo :: #file_info{} | 'undefined')
+ -> {ok, [string()]} | {error,_}.
-set_primary_archive(undefined, undefined) ->
- request({set_primary_archive, undefined, undefined});
-set_primary_archive(File, ArchiveBin)
- when is_list(File), is_binary(ArchiveBin) ->
- request({set_primary_archive, File, ArchiveBin}).
+set_primary_archive(undefined, undefined, undefined) ->
+ request({set_primary_archive, undefined, undefined, undefined});
+set_primary_archive(File, ArchiveBin, FileInfo)
+ when is_list(File), is_binary(ArchiveBin), is_record(FileInfo, file_info) ->
+ request({set_primary_archive, File, ArchiveBin, FileInfo}).
-spec release_archives() -> 'ok' | {'error', _}.
@@ -315,8 +316,8 @@ loop(State, Parent, Paths) ->
{get_cwd,[_]=Args} ->
{Res,State1} = handle_get_cwd(State, Args),
{Res,State1,Paths};
- {set_primary_archive,File,Bin} ->
- {Res,State1} = handle_set_primary_archive(State, File, Bin),
+ {set_primary_archive,File,Bin,FileInfo} ->
+ {Res,State1} = handle_set_primary_archive(State, File, Bin,FileInfo),
{Res,State1,Paths};
release_archives ->
{Res,State1} = handle_release_archives(State),
@@ -356,8 +357,8 @@ handle_get_file(State = #state{loader = efile}, Paths, File) ->
handle_get_file(State = #state{loader = inet}, Paths, File) ->
?SAFE2(inet_get_file_from_port(State, File, Paths), State).
-handle_set_primary_archive(State= #state{loader = efile}, File, Bin) ->
- ?SAFE2(efile_set_primary_archive(State, File, Bin), State).
+handle_set_primary_archive(State= #state{loader = efile}, File, Bin, FileInfo) ->
+ ?SAFE2(efile_set_primary_archive(State, File, Bin, FileInfo), State).
handle_release_archives(State= #state{loader = efile}) ->
?SAFE2(efile_release_archives(State), State).
@@ -481,8 +482,8 @@ efile_get_file_from_port3(State, File, [P | Paths]) ->
efile_get_file_from_port3(State, _File, []) ->
{{error,enoent},State}.
-efile_set_primary_archive(#state{prim_state = PS} = State, File, Bin) ->
- {Res, PS2} = prim_set_primary_archive(PS, File, Bin),
+efile_set_primary_archive(#state{prim_state = PS} = State, File, Bin, FileInfo) ->
+ {Res, PS2} = prim_set_primary_archive(PS, File, Bin, FileInfo),
{Res,State#state{prim_state = PS2}}.
efile_release_archives(#state{prim_state = PS} = State) ->
@@ -572,13 +573,14 @@ find_loop(U, Retry, AL, ReqDelay, SReSleep, Ignore, Tries, LReSleep) ->
case find_loop(U, Retry, AL, ReqDelay, []) of
[] -> % no response from any server
erlang:display({erl_prim_loader,'no server found'}), % lifesign
- Tries1 = if Tries > 0 ->
- sleep(SReSleep),
- Tries - 1;
- true ->
- sleep(LReSleep),
- 0
- end,
+ Tries1 =
+ if Tries > 0 ->
+ sleep(SReSleep),
+ Tries - 1;
+ true ->
+ sleep(LReSleep),
+ 0
+ end,
find_loop(U, Retry, AL, ReqDelay, SReSleep, Ignore, Tries1, LReSleep);
Servers ->
keysort(1, Servers -- Ignore)
@@ -787,9 +789,9 @@ prim_release_archives(PS) ->
prim_do_release_archives(PS, [{ArchiveFile, DictVal} | KeyVals], Acc) ->
Res =
case DictVal of
- {primary, _PrimZip} ->
+ {primary, _PrimZip, _FI} ->
ok; % Keep primary archive
- {_Mtime, Cache} ->
+ {Cache, _FI} ->
debug(PS, {release, cache, ArchiveFile}),
erase(ArchiveFile),
clear_cache(ArchiveFile, Cache)
@@ -805,7 +807,7 @@ prim_do_release_archives(PS, [], []) ->
prim_do_release_archives(PS, [], Errors) ->
{{error, Errors}, PS#prim_state{primary_archive = undefined}}.
-prim_set_primary_archive(PS, undefined, undefined) ->
+prim_set_primary_archive(PS, undefined, undefined, undefined) ->
debug(PS, {set_primary_archive, clean}),
case PS#prim_state.primary_archive of
undefined ->
@@ -813,15 +815,15 @@ prim_set_primary_archive(PS, undefined, undefined) ->
debug(PS, {return, Res}),
{Res, PS};
ArchiveFile ->
- {primary, PrimZip} = erase(ArchiveFile),
+ {primary, PrimZip, _FI} = erase(ArchiveFile),
ok = prim_zip:close(PrimZip),
PS2 = PS#prim_state{primary_archive = undefined},
Res = {ok, []},
debug(PS2, {return, Res}),
{Res, PS2}
end;
-prim_set_primary_archive(PS, ArchiveFile, ArchiveBin)
- when is_list(ArchiveFile), is_binary(ArchiveBin) ->
+prim_set_primary_archive(PS, ArchiveFile, ArchiveBin, FileInfo)
+ when is_list(ArchiveFile), is_binary(ArchiveBin), is_record(FileInfo, file_info) ->
%% Try the archive file
debug(PS, {set_primary_archive, ArchiveFile, byte_size(ArchiveBin)}),
{Res3, PS3} =
@@ -833,17 +835,17 @@ prim_set_primary_archive(PS, ArchiveFile, ArchiveBin)
["", "nibe", RevApp] -> % Reverse ebin
%% Collect ebin directories in archive
Ebin = reverse(RevApp) ++ "/ebin",
- {true, [Ebin | A]};
+ {true, [Ebin | A]};
_ ->
{true, A}
end
end,
Ebins0 = [ArchiveFile],
- case open_archive({ArchiveFile, ArchiveBin}, Ebins0, Fun) of
- {ok, PrimZip, RevEbins} ->
+ case open_archive({ArchiveFile, ArchiveBin}, FileInfo, Ebins0, Fun) of
+ {ok, PrimZip, {RevEbins, FI, _}} ->
Ebins = reverse(RevEbins),
debug(PS, {set_primary_archive, Ebins}),
- put(ArchiveFile, {primary, PrimZip}),
+ put(ArchiveFile, {primary, PrimZip, FI}),
{{ok, Ebins}, PS#prim_state{primary_archive = ArchiveFile}};
Error ->
debug(PS, {set_primary_archive, Error}),
@@ -851,10 +853,10 @@ prim_set_primary_archive(PS, ArchiveFile, ArchiveBin)
end;
OldArchiveFile ->
debug(PS, {set_primary_archive, clean}),
- PrimZip = erase(OldArchiveFile),
+ {primary, PrimZip, _FI} = erase(OldArchiveFile),
ok = prim_zip:close(PrimZip),
PS2 = PS#prim_state{primary_archive = undefined},
- prim_set_primary_archive(PS2, ArchiveFile, ArchiveBin)
+ prim_set_primary_archive(PS2, ArchiveFile, ArchiveBin, FileInfo)
end,
debug(PS3, {return, Res3}),
{Res3, PS3}.
@@ -956,15 +958,15 @@ prim_read_file_info(PS, File) ->
FunnyFile = funny_split(FileInArchive, $/),
Fun =
fun({Funny, GetInfo, _GetBin}, Acc) ->
- if
- hd(Funny) =:= "",
- tl(Funny) =:= FunnyFile ->
+ case Funny of
+ [H | T] when H =:= "",
+ T =:= FunnyFile ->
%% Directory
{false, {ok, GetInfo()}};
- Funny =:= FunnyFile ->
+ F when F =:= FunnyFile ->
%% Plain file
{false, {ok, GetInfo()}};
- true ->
+ _ ->
%% No match
{true, Acc}
end
@@ -990,33 +992,36 @@ prim_get_cwd(PS, [Drive]) ->
apply_archive(PS, Fun, Acc, Archive) ->
case get(Archive) of
undefined ->
+ case open_archive(Archive, Acc, Fun) of
+ {ok, PrimZip, {Acc2, FI, _}} ->
+ debug(PS, {cache, ok}),
+ put(Archive, {{ok, PrimZip}, FI}),
+ {Acc2, PS};
+ Error ->
+ debug(PS, {cache, Error}),
+ %% put(Archive, {Error, FI}),
+ {Error, PS}
+ end;
+ {primary, PrimZip, FI} ->
+ case prim_file:read_file_info(Archive) of
+ {ok, FI2}
+ when FI#file_info.mtime =:= FI2#file_info.mtime ->
+ case foldl_archive(PrimZip, Acc, Fun) of
+ {ok, _PrimZip2, Acc2} ->
+ {Acc2, PS};
+ Error ->
+ debug(PS, {primary, Error}),
+ {Error, PS}
+ end;
+ Error ->
+ debug(PS, {cache, {clear, Error}}),
+ clear_cache(Archive, {ok, PrimZip}),
+ apply_archive(PS, Fun, Acc, Archive)
+ end;
+ {Cache, FI} ->
case prim_file:read_file_info(Archive) of
- {ok, #file_info{mtime = Mtime}} ->
- case open_archive(Archive, Acc, Fun) of
- {ok, PrimZip, Acc2} ->
- debug(PS, {cache, ok}),
- put(Archive, {Mtime, {ok, PrimZip}}),
- {Acc2, PS};
- Error ->
- debug(PS, {cache, Error}),
- put(Archive, {Mtime, Error}),
- {Error, PS}
- end;
- Error ->
- debug(PS, {cache, Error}),
- {Error, PS}
- end;
- {primary, PrimZip} ->
- case foldl_archive(PrimZip, Acc, Fun) of
- {ok, _PrimZip2, Acc2} ->
- {Acc2, PS};
- Error ->
- debug(PS, {primary, Error}),
- {Error, PS}
- end;
- {Mtime, Cache} ->
- case prim_file:read_file_info(Archive) of
- {ok, #file_info{mtime = Mtime2}} when Mtime2 =:= Mtime ->
+ {ok, FI2}
+ when FI#file_info.mtime =:= FI2#file_info.mtime ->
case Cache of
{ok, PrimZip} ->
case foldl_archive(PrimZip, Acc, Fun) of
@@ -1026,7 +1031,8 @@ apply_archive(PS, Fun, Acc, Archive) ->
debug(PS, {cache, {clear, Error}}),
clear_cache(Archive, Cache),
debug(PS, {cache, Error}),
- put(Archive, {Mtime, Error}),
+ erase(Archive),
+ %% put(Archive, {Error, FI}),
{Error, PS}
end;
Error ->
@@ -1041,20 +1047,57 @@ apply_archive(PS, Fun, Acc, Archive) ->
end.
open_archive(Archive, Acc, Fun) ->
+ case prim_file:read_file_info(Archive) of
+ {ok, FileInfo} ->
+ open_archive(Archive, FileInfo, Acc, Fun);
+ {error, Reason} ->
+ {error, Reason}
+ end.
+
+open_archive(Archive, FileInfo, Acc, Fun) ->
+ FakeFI = FileInfo#file_info{type = directory},
Wrapper =
- fun({N, GI, GB}, A) ->
- %% Ensure full iteration at open
- Funny = funny_split(N, $/),
- {_Continue, A2} = Fun({Funny, GI, GB}, A),
- {true, {true, Funny}, A2}
- end,
- prim_zip:open(Wrapper, Acc, Archive).
+ fun({N, GI, GB}, {A, I, FunnyDirs}) -> % Full iteration at open
+ Funny = funny_split(N, $/),
+ FunnyDirs2 =
+ case Funny of
+ ["" | FunnyDir] ->
+ [FunnyDir | FunnyDirs];
+ _ ->
+ FunnyDirs
+ end,
+ {Includes, FunnyDirs3, A2} =
+ ensure_virtual_dirs(Funny, Fun, FakeFI, [{true, Funny}], FunnyDirs2, A),
+ {_Continue, A3} = Fun({Funny, GI, GB}, A2),
+ {true, Includes, {A3, I, FunnyDirs3}}
+ end,
+ prim_zip:open(Wrapper, {Acc, FakeFI, []}, Archive).
+
+ensure_virtual_dirs(Funny, Fun, FakeFI, Includes, FunnyDirs, Acc) ->
+ case Funny of
+ [_ | FunnyDir] ->
+ case lists:member(FunnyDir, FunnyDirs) of % BIF
+ false ->
+ GetInfo = fun() -> FakeFI end,
+ GetBin = fun() -> <<>> end,
+ VirtualDir = ["" | FunnyDir],
+ Includes2 = [{true, VirtualDir, GetInfo, GetBin} | Includes],
+ FunnyDirs2 = [FunnyDir | FunnyDirs],
+ {I, F, Acc2} = ensure_virtual_dirs(FunnyDir, Fun, FakeFI, Includes2, FunnyDirs2, Acc),
+ {_Continue, Acc3} = Fun({VirtualDir, GetInfo, GetBin}, Acc2),
+ {I, F, Acc3};
+ true ->
+ {reverse(Includes), FunnyDirs, Acc}
+ end;
+ [] ->
+ {reverse(Includes), FunnyDirs, Acc}
+ end.
foldl_archive(PrimZip, Acc, Fun) ->
Wrapper =
- fun({N, GI, GB}, A) ->
+ fun({Funny, GI, GB}, A) ->
%% Allow partial iteration at foldl
- {Continue, A2} = Fun({N, GI, GB}, A),
+ {Continue, A2} = Fun({Funny, GI, GB}, A),
{Continue, true, A2}
end,
prim_zip:foldl(Wrapper, Acc, PrimZip).
diff --git a/erts/preloaded/src/prim_zip.erl b/erts/preloaded/src/prim_zip.erl
index 17ef8c6c43..3f5a5b9721 100644
--- a/erts/preloaded/src/prim_zip.erl
+++ b/erts/preloaded/src/prim_zip.erl
@@ -1,19 +1,19 @@
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2008-2009. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
%% compliance with the License. You should have received a copy of the
%% Erlang Public License along with this software. If not, it can be
%% retrieved online at http://www.erlang.org/.
-%%
+%%
%% Software distributed under the License is distributed on an "AS IS"
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
%% the License for the specific language governing rights and limitations
%% under the License.
-%%
+%%
%% %CopyrightEnd%
%%
@@ -94,12 +94,7 @@ do_foldl(FilterFun, FilterAcc, [PF | Tail], Acc0, PrimZip, PrimZipOrig) ->
#primzip_file{name = F, get_info = GetInfo, get_bin = GetBin} = PF,
case FilterFun({F, GetInfo, GetBin}, FilterAcc) of
{Continue, Include, FilterAcc2} ->
- Acc1 =
- case Include of
- false -> Acc0;
- true -> [PF | Acc0];
- {true, Nick} -> [PF#primzip_file{name = Nick} | Acc0]
- end,
+ Acc1 = include_acc(Include, PF, Acc0),
case Continue of
true ->
do_foldl(FilterFun, FilterAcc2, Tail, Acc1, PrimZip, PrimZipOrig);
@@ -112,6 +107,28 @@ do_foldl(FilterFun, FilterAcc, [PF | Tail], Acc0, PrimZip, PrimZipOrig) ->
do_foldl(_FilterFun, FilterAcc, [], Acc, PrimZip, _PrimZipOrig) ->
{ok, FilterAcc, PrimZip#primzip{files = reverse(Acc)}}.
+include_acc(Include, PF, Acc) ->
+ case Include of
+ false ->
+ Acc;
+ true ->
+ [PF | Acc];
+ {true, Nick} ->
+ [PF#primzip_file{name = Nick} | Acc];
+ {true, Nick, GetInfo, GetBin} ->
+ PF2 = #primzip_file{name = Nick, get_info = GetInfo, get_bin = GetBin},
+ [PF2 | Acc];
+ List when is_list(List) ->
+ %% Add new entries
+ Fun = fun(I, A) -> include_acc(I, PF, A) end,
+ lists_foldl(Fun, Acc, List)
+ end.
+
+lists_foldl(F, Accu, [Hd|Tail]) ->
+ lists_foldl(F, F(Hd, Accu), Tail);
+lists_foldl(F, Accu, []) when is_function(F, 2) ->
+ Accu.
+
%% close a zip archive
close(#primzip{in = In0, input = Input, zlib = Z}) ->
Input(close, In0),
@@ -199,15 +216,25 @@ get_cd_loop(N, BCD, Acc0, PrimZip, FileName, Offset, CFH, EndOffset, FilterFun,
end,
%% erlang:display({FileName, N, Offset, Size, NextPF}),
GetInfo = fun() -> cd_file_header_to_file_info(FileName, CFH, <<>>) end,
- GetBin = fun() -> get_z_file(FileName, Offset, Size, PrimZip) end,
+ GetBin = fun() -> get_z_file(FileName, Offset, Size, PrimZip) end,
PF = #primzip_file{name = FileName, get_info = GetInfo, get_bin = GetBin},
case FilterFun({FileName, GetInfo, GetBin}, FilterAcc) of
{Continue, Include, FilterAcc2} ->
Acc1 =
case Include of
- false -> Acc0;
- true -> [PF | Acc0];
- {true, Nick} -> [PF#primzip_file{name = Nick} | Acc0]
+ false ->
+ Acc0;
+ true ->
+ [PF | Acc0];
+ {true, Nick} ->
+ [PF#primzip_file{name = Nick} | Acc0];
+ {true, Nick, GI, GB} ->
+ PF2 = #primzip_file{name = Nick, get_info = GI, get_bin = GB},
+ [PF2 | Acc0];
+ List when is_list(List) ->
+ %% Add new entries
+ Fun = fun(I, A) -> include_acc(I, PF, A) end,
+ lists_foldl(Fun, Acc0, List)
end,
case Continue of
true when N > 1 ->
diff --git a/lib/kernel/src/code.erl b/lib/kernel/src/code.erl
index fef11d7e6e..89d893f8c1 100644
--- a/lib/kernel/src/code.erl
+++ b/lib/kernel/src/code.erl
@@ -1,19 +1,19 @@
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 1996-2010. All Rights Reserved.
+%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
%% compliance with the License. You should have received a copy of the
%% Erlang Public License along with this software. If not, it can be
%% retrieved online at http://www.erlang.org/.
-%%
+%%
%% Software distributed under the License is distributed on an "AS IS"
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
%% the License for the specific language governing rights and limitations
%% under the License.
-%%
+%%
%% %CopyrightEnd%
%%
-module(code).
@@ -63,7 +63,7 @@
which/1,
where_is_file/1,
where_is_file/2,
- set_primary_archive/2,
+ set_primary_archive/3,
clash/0]).
-include_lib("kernel/include/file.hrl").
@@ -101,7 +101,7 @@
%% unstick_dir(Dir) -> ok | error
%% is_sticky(Module) -> true | false
%% which(Module) -> Filename
-%% set_primary_archive((FileName, Bin) -> ok | {error, Reason}
+%% set_primary_archive((FileName, Bin, FileInfo) -> ok | {error, Reason}
%% clash() -> -> print out
%%----------------------------------------------------------------------------
@@ -420,11 +420,15 @@ where_is_file(Path, File) when is_list(Path), is_list(File) ->
which(File, ".", Path)
end.
--spec set_primary_archive(ArchiveFile :: file:filename(), ArchiveBin :: binary()) -> 'ok' | {'error', atom()}.
+-spec set_primary_archive(ArchiveFile :: file:filename(),
+ ArchiveBin :: binary(),
+ FileInfo :: #file_info{})
+ -> 'ok' | {'error', atom()}.
-set_primary_archive(ArchiveFile0, ArchiveBin) when is_list(ArchiveFile0), is_binary(ArchiveBin) ->
+set_primary_archive(ArchiveFile0, ArchiveBin, FileInfo)
+ when is_list(ArchiveFile0), is_binary(ArchiveBin), is_record(FileInfo, file_info) ->
ArchiveFile = filename:absname(ArchiveFile0),
- case call({set_primary_archive, ArchiveFile, ArchiveBin}) of
+ case call({set_primary_archive, ArchiveFile, ArchiveBin, FileInfo}) of
{ok, []} ->
ok;
{ok, _Mode, Ebins} ->
diff --git a/lib/kernel/src/code_server.erl b/lib/kernel/src/code_server.erl
index d4e3f0bcf8..7aeddb73d1 100644
--- a/lib/kernel/src/code_server.erl
+++ b/lib/kernel/src/code_server.erl
@@ -1,19 +1,19 @@
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1998-2009. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 1998-2010. All Rights Reserved.
+%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
%% compliance with the License. You should have received a copy of the
%% Erlang Public License along with this software. If not, it can be
%% retrieved online at http://www.erlang.org/.
-%%
+%%
%% Software distributed under the License is distributed on an "AS IS"
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
%% the License for the specific language governing rights and limitations
%% under the License.
-%%
+%%
%% %CopyrightEnd%
%%
-module(code_server).
@@ -384,8 +384,8 @@ handle_call(stop,{_From,_Tag}, S) ->
handle_call({is_cached,_File}, {_From,_Tag}, S=#state{cache=no_cache}) ->
{reply, no, S};
-handle_call({set_primary_archive, File, ArchiveBin}, {_From,_Tag}, S=#state{mode=Mode}) ->
- case erl_prim_loader:set_primary_archive(File, ArchiveBin) of
+handle_call({set_primary_archive, File, ArchiveBin, FileInfo}, {_From,_Tag}, S=#state{mode=Mode}) ->
+ case erl_prim_loader:set_primary_archive(File, ArchiveBin, FileInfo) of
{ok, Files} ->
{reply, {ok, Mode, Files}, S};
{error, Reason} ->
diff --git a/lib/kernel/test/erl_prim_loader_SUITE.erl b/lib/kernel/test/erl_prim_loader_SUITE.erl
index 4d090f4db5..19c84ab34c 100644
--- a/lib/kernel/test/erl_prim_loader_SUITE.erl
+++ b/lib/kernel/test/erl_prim_loader_SUITE.erl
@@ -1,19 +1,19 @@
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 1996-2010. All Rights Reserved.
+%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
%% compliance with the License. You should have received a copy of the
%% Erlang Public License along with this software. If not, it can be
%% retrieved online at http://www.erlang.org/.
-%%
+%%
%% Software distributed under the License is distributed on an "AS IS"
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
%% the License for the specific language governing rights and limitations
%% under the License.
-%%
+%%
%% %CopyrightEnd%
%%
-module(erl_prim_loader_SUITE).
@@ -27,7 +27,7 @@
inet_existing/1, inet_coming_up/1, inet_disconnects/1,
multiple_slaves/1, file_requests/1,
local_archive/1, remote_archive/1,
- primary_archive/1]).
+ primary_archive/1, virtual_dir_in_archive/1]).
-export([init_per_testcase/2, fin_per_testcase/2]).
@@ -41,10 +41,11 @@ all(suite) ->
inet_existing, inet_coming_up,
inet_disconnects, multiple_slaves,
file_requests, local_archive,
- remote_archive, primary_archive
+ remote_archive, primary_archive,
+ virtual_dir_in_archive
].
-init_per_testcase(Func, Config) when atom(Func), list(Config) ->
+init_per_testcase(Func, Config) when is_atom(Func), is_list(Config) ->
Dog=?t:timetrap(?t:minutes(3)),
[{watchdog, Dog}|Config].
@@ -81,7 +82,7 @@ set_path(Config) when is_list(Config) ->
get_file(doc) -> [];
get_file(Config) when is_list(Config) ->
?line case erl_prim_loader:get_file("lists" ++ code:objfile_extension()) of
- {ok,Bin,File} when binary(Bin), list(File) ->
+ {ok,Bin,File} when is_binary(Bin), is_list(File) ->
ok;
_ ->
test_server:fail(get_valid_file)
@@ -344,8 +345,9 @@ local_archive(Config) when is_list(Config) ->
Node = node(),
BeamName = "inet.beam",
?line ok = test_archive(Node, Archive, KernelDir, BeamName),
- ?line ok = rpc:call(Node, erl_prim_loader, release_archives, []),
+ %% Cleanup
+ ?line ok = rpc:call(Node, erl_prim_loader, release_archives, []),
?line ok = file:delete(Archive),
ok.
@@ -365,6 +367,7 @@ remote_archive(Config) when is_list(Config) ->
BeamName = "inet.beam",
?line ok = test_archive(Node, Archive, KernelDir, BeamName),
+ %% Cleanup
?line stop_node(Node),
?line unlink(BootPid),
?line exit(BootPid, kill),
@@ -401,21 +404,22 @@ primary_archive(Config) when is_list(Config) ->
?line Args = " -setcookie " ++ Cookie,
?line {ok,Node} = start_node(primary_archive, Args),
?line wait_really_started(Node, 25),
+ ?line {_,_,_} = rpc:call(Node, erlang, date, []),
%% Set primary archive
- ?line {_,_,_} = rpc:call(Node, erlang, date, []),
- ?line {ok, Ebins} = rpc:call(Node, erl_prim_loader, set_primary_archive, [Archive, ArchiveBin]),
ExpectedEbins = [Archive, DictDir ++ "/ebin", DummyDir ++ "/ebin"],
io:format("ExpectedEbins: ~p\n", [ExpectedEbins]),
- ?line ExpectedEbins = lists:sort(Ebins),
+ ?line {ok, FileInfo} = prim_file:read_file_info(Archive),
+ ?line {ok, Ebins} = rpc:call(Node, erl_prim_loader, set_primary_archive, [Archive, ArchiveBin, FileInfo]),
+ ?line ExpectedEbins = lists:sort(Ebins), % assert
?line {ok, TopFiles2} = rpc:call(Node, erl_prim_loader, list_dir, [Archive]),
?line [DictDir, DummyDir] = lists:sort(TopFiles2),
BeamName = "primary_archive_dict_app.beam",
?line ok = test_archive(Node, Archive, DictDir, BeamName),
- ?line {ok, []} = rpc:call(Node, erl_prim_loader, set_primary_archive, [undefined, undefined]),
-
+ %% Cleanup
+ ?line {ok, []} = rpc:call(Node, erl_prim_loader, set_primary_archive, [undefined, undefined, undefined]),
?line stop_node(Node),
?line ok = file:delete(Archive),
ok.
@@ -461,6 +465,46 @@ create_archive(Archive, AppDirs) ->
io:format("zip:create(~p,\n\t~p,\n\t~p).\n", [Archive, AppDirs, Opts]),
zip:create(Archive, AppDirs, Opts).
+
+virtual_dir_in_archive(suite) ->
+ [];
+virtual_dir_in_archive(doc) ->
+ ["Read virtual directories from archive."];
+virtual_dir_in_archive(Config) when is_list(Config) ->
+ PrivDir = ?config(priv_dir, Config),
+ Data = <<"A little piece of data.">>,
+ ArchiveBase = "archive_with_virtual_dirs",
+ Archive = filename:join([PrivDir, ArchiveBase ++ init:archive_extension()]),
+ FileBase = "a_data_file.beam",
+ EbinBase = "ebin",
+ FileInArchive = filename:join([ArchiveBase, EbinBase, FileBase]),
+ BinFiles = [{FileInArchive, Data}],
+ Opts = [{compress, []}],
+ ?line file:delete(Archive),
+ io:format("zip:create(~p,\n\t~p,\n\t~p).\n", [Archive, BinFiles, Opts]),
+ ?line {ok, Archive} = zip:create(Archive, BinFiles, Opts),
+
+ %% Verify that there is no directories
+ ?line {ok, BinFiles} = zip:unzip(Archive, [memory]),
+
+ FullPath = filename:join([Archive, FileInArchive]),
+ ?line {ok, _} = erl_prim_loader:read_file_info(FullPath),
+
+ %% Read one virtual dir
+ EbinDir = filename:dirname(FullPath),
+ ?line {ok, _} = erl_prim_loader:read_file_info(EbinDir),
+ ?line {ok, [FileBase]} = erl_prim_loader:list_dir(EbinDir),
+
+ %% Read another virtual dir
+ AppDir = filename:dirname(EbinDir),
+ ?line {ok, _} = erl_prim_loader:read_file_info(AppDir),
+ ?line {ok, [EbinBase]} = erl_prim_loader:list_dir(AppDir),
+
+ %% Cleanup
+ ?line ok = erl_prim_loader:release_archives(),
+ ?line ok = file:delete(Archive),
+ ok.
+
%% Misc. functions
ip_str({A, B, C, D}) ->
diff --git a/lib/stdlib/src/escript.erl b/lib/stdlib/src/escript.erl
index 697a69b801..c0f71fb3f5 100644
--- a/lib/stdlib/src/escript.erl
+++ b/lib/stdlib/src/escript.erl
@@ -1,19 +1,19 @@
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2007-2009. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 2007-2010. All Rights Reserved.
+%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
%% compliance with the License. You should have received a copy of the
%% Erlang Public License along with this software. If not, it can be
%% retrieved online at http://www.erlang.org/.
-%%
+%%
%% Software distributed under the License is distributed on an "AS IS"
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
%% the License for the specific language governing rights and limitations
%% under the License.
-%%
+%%
%% %CopyrightEnd%
-module(escript).
@@ -180,7 +180,8 @@ parse_and_run(File, Args, Options) ->
is_binary(FormsOrBin) ->
case Source of
archive ->
- case code:set_primary_archive(File, FormsOrBin) of
+ {ok, FileInfo} = file:read_file_info(File),
+ case code:set_primary_archive(File, FormsOrBin, FileInfo) of
ok when CheckOnly ->
case code:load_file(Module) of
{module, _} ->