aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSiri Hansen <[email protected]>2012-07-09 18:05:09 +0200
committerSiri Hansen <[email protected]>2012-07-10 09:55:45 +0200
commitfc241fdbfacdca72f219a601ed16fb9cb6159063 (patch)
tree1ced57f350b225c936f5d5c0280469e193226787
parent13d135515cabfe4e741a4350cfe294e041c06158 (diff)
downloadotp-fc241fdbfacdca72f219a601ed16fb9cb6159063.tar.gz
otp-fc241fdbfacdca72f219a601ed16fb9cb6159063.tar.bz2
otp-fc241fdbfacdca72f219a601ed16fb9cb6159063.zip
Add tests for problems with handling of primary archive
Thanks to Tuncer Ayaz for co-authoring.
-rw-r--r--lib/stdlib/test/escript_SUITE.erl126
-rw-r--r--lib/stdlib/test/escript_SUITE_data/archive_script_file_access/archive_script_file_access.erl86
2 files changed, 210 insertions, 2 deletions
diff --git a/lib/stdlib/test/escript_SUITE.erl b/lib/stdlib/test/escript_SUITE.erl
index 7ed1ee742a..253b18ecb0 100644
--- a/lib/stdlib/test/escript_SUITE.erl
+++ b/lib/stdlib/test/escript_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2012. 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
@@ -29,6 +29,7 @@
module_script/1,
beam_script/1,
archive_script/1,
+ archive_script_file_access/1,
epp/1,
create_and_extract/1,
foldl/1,
@@ -44,7 +45,8 @@ suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
[basic, errors, strange_name, emulator_flags,
module_script, beam_script, archive_script, epp,
- create_and_extract, foldl, overflow].
+ create_and_extract, foldl, overflow,
+ archive_script_file_access].
groups() ->
[].
@@ -464,6 +466,126 @@ archive_script(Config) when is_list(Config) ->
ok.
+%% Test the correction of OTP-10071
+%% The errors identified are
+%%
+%% * If primary archive was named "xxx", then a file in the same
+%% directory named "xxxyyy" would be interpreted as a file named yyy
+%% inside the archive.
+%%
+%% * erl_prim_loader did not correctly create and normalize absolute
+%% paths for primary archive and files inside it, so unless given
+%% with exact same path files inside the archive would not be
+%% found. E.g. if escript was started as ./xxx then "xxx/file" would
+%% not be found since erl_prim_loader would try to match
+%% /full/path/to/xxx with /full/path/to/./xxx. Same problem with
+%% ../
+%%
+%% * Depending on how the primary archive was built,
+%% erl_prim_loader:list_dir/1 would sometimes return an empty string
+%% inside the file list. This was a virtual element representing the
+%% top directory of the archive. This shall not occur.
+%%
+archive_script_file_access(Config) when is_list(Config) ->
+ %% Copy the orig files to priv_dir
+ DataDir = ?config(data_dir, Config),
+ PrivDir = ?config(priv_dir, Config),
+
+ MainMod = "archive_script_file_access",
+ MainSrc = MainMod ++ ".erl",
+ MainBeam = MainMod ++ ".beam",
+
+ Archive = filename:join([PrivDir, "archive_script_file_access.zip"]),
+ ?line {ok, _} = zip:create(Archive, ["archive_script_file_access"],
+ [{compress, []}, {cwd, DataDir}]),
+ ?line {ok, _} = zip:extract(Archive, [{cwd, PrivDir}]),
+ TopDir = filename:join([PrivDir, "archive_script_file_access"]),
+
+ %% Compile the code
+ ?line ok = compile_files([MainSrc], TopDir, TopDir),
+
+ %% First, create a file structure which will be included in the archive:
+ %%
+ %% dir1/
+ %% dir1/subdir1/
+ %% dir1/subdir1/file1
+ %%
+ {ok, OldDir} = file:get_cwd(),
+ ok = file:set_cwd(TopDir),
+ DummyDir = "dir1",
+ DummySubDir = filename:join(DummyDir, "subdir1"),
+ RelDummyFile = filename:join(DummySubDir, "file1"),
+ DummyFile = filename:join(TopDir,RelDummyFile),
+ ok = filelib:ensure_dir(DummyFile),
+ ok = file:write_file(DummyFile, ["foo\nbar\nbaz"]),
+
+ %% 1. Create zip archive by adding the dummy file and the beam
+ %% file as binaries to zip.
+ %%
+ %% This used to provoke the following issues when the script was run as
+ %% "./<script_name>":
+ %% a. erl_prim_loader:read_file_info/1 returning 'error'
+ %% b. erl_prim_loader:list_dir/1 returning {ok, ["dir1", [], "file1"]}
+ %% leading to an infinite loop in reltool_target:spec_dir/1
+ Files1 =
+ lists:map(fun(Filename) ->
+ {ok, Bin} = file:read_file(Filename),
+ {Filename,Bin}
+ end,
+ [RelDummyFile,MainBeam]),
+ {ok, {"mem", Bin1}} = zip:create("mem", Files1, [memory]),
+
+ %% Create the escript
+ ScriptName1 = "archive_script_file_access1",
+ Script1 = filename:join([PrivDir, ScriptName1]),
+ Flags = "-escript main " ++ MainMod,
+ ok = escript:create(Script1,[shebang,{emu_args,Flags},{archive,Bin1}]),
+ ok = file:change_mode(Script1,8#00744),
+
+ %% Also add a dummy file in the same directory with the same name
+ %% as the script except is also has an extension. This used to
+ %% cause erl_prim_loader to believe it was a file inside the
+ %% script.
+ ok = file:write_file(Script1 ++ ".extension",
+ <<"same name as script, but with extension">>),
+
+ %% Change to script's directory and run it as "./<script_name>"
+ ok = file:set_cwd(PrivDir),
+ do_run(PrivDir, "./" ++ ScriptName1,
+ [<<"file_access:[]\n",
+ "ExitCode:0">>]),
+ ok = file:set_cwd(TopDir),
+
+
+ %% 2. Create zip archive by letting zip read the files from the file system
+ %%
+ %% The difference compared to the archive_script_file_access1 is
+ %% that this will have a file element for each directory in the
+ %% archive - while archive_script_file_access1 will only have a
+ %% file element per regular file.
+ Files2 = [DummyDir,MainBeam],
+ {ok, {"mem", Bin2}} = zip:create("mem", Files2, [memory]),
+
+ %% Create the escript
+ ScriptName2 = "archive_script_file_access2",
+ Script2 = filename:join([PrivDir, ScriptName2]),
+ ok = escript:create(Script2,[shebang,{emu_args,Flags},{archive,Bin2}]),
+ ok = file:change_mode(Script2,8#00744),
+
+ %% Also add a dummy file in the same directory with the same name
+ %% as the script except is also has an extension. This used to
+ %% cause erl_prim_loader to believe it was a file inside the
+ %% script.
+ ok = file:write_file(Script2 ++ ".extension",
+ <<"same name as script, but with extension">>),
+
+ %% Change to script's directory and run it as "./<script_name>"
+ ok = file:set_cwd(PrivDir),
+ do_run(PrivDir, "./" ++ ScriptName2,
+ [<<"file_access:[]\n",
+ "ExitCode:0">>]),
+ ok = file:set_cwd(OldDir).
+
compile_app(TopDir, AppName) ->
AppDir = filename:join([TopDir, AppName]),
SrcDir = filename:join([AppDir, "src"]),
diff --git a/lib/stdlib/test/escript_SUITE_data/archive_script_file_access/archive_script_file_access.erl b/lib/stdlib/test/escript_SUITE_data/archive_script_file_access/archive_script_file_access.erl
new file mode 100644
index 0000000000..226a8675db
--- /dev/null
+++ b/lib/stdlib/test/escript_SUITE_data/archive_script_file_access/archive_script_file_access.erl
@@ -0,0 +1,86 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2012. 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(archive_script_file_access).
+-behaviour(escript).
+
+-export([main/1]).
+
+-include_lib("kernel/include/file.hrl").
+
+main(MainArgs) ->
+ io:format("file_access:~p\n", [MainArgs]),
+ ArchiveFile = escript:script_name(),
+
+ AbsArchiveFile = filename:absname(ArchiveFile),
+ RelArchiveFile = filename:basename(ArchiveFile),
+ DotSlashArchiveFile = "./" ++ RelArchiveFile,
+
+ Beam = atom_to_list(?MODULE) ++ ".beam",
+ AbsBeam = filename:join(AbsArchiveFile,Beam),
+ RelBeam = filename:join(RelArchiveFile,Beam),
+ DotSlashBeam = filename:join(DotSlashArchiveFile,Beam),
+ Dir = "dir1",
+ AbsDir = filename:join(AbsArchiveFile,Dir),
+ RelDir = filename:join(RelArchiveFile,Dir),
+ DotSlashDir = filename:join(DotSlashArchiveFile,Dir),
+
+ {ok,List1} = erl_prim_loader:list_dir(AbsArchiveFile),
+ {ok,List1} = erl_prim_loader:list_dir(RelArchiveFile),
+ {ok,List1} = erl_prim_loader:list_dir(DotSlashArchiveFile),
+ {ok,List1} = erl_prim_loader:list_dir(AbsArchiveFile ++ "/"),
+ {ok,List1} = erl_prim_loader:list_dir(AbsArchiveFile ++ "/."),
+ {ok,List1} = erl_prim_loader:list_dir(filename:join([AbsDir,".."])),
+ {ok,List1} = erl_prim_loader:list_dir(filename:join([RelDir,".."])),
+ {ok,List1} = erl_prim_loader:list_dir(filename:join([DotSlashDir,".."])),
+ false = lists:member([],List1),
+
+ {ok,List2} = erl_prim_loader:list_dir(AbsDir),
+ {ok,List2} = erl_prim_loader:list_dir(RelDir),
+ {ok,List2} = erl_prim_loader:list_dir(DotSlashDir),
+ false = lists:member([],List2),
+
+ error = erl_prim_loader:list_dir(AbsBeam),
+ error = erl_prim_loader:list_dir(RelBeam),
+ error = erl_prim_loader:list_dir(DotSlashBeam),
+
+ error = erl_prim_loader:get_file(AbsArchiveFile),
+ error = erl_prim_loader:get_file(RelArchiveFile),
+ error = erl_prim_loader:get_file(DotSlashArchiveFile),
+ error = erl_prim_loader:get_file(AbsArchiveFile ++ "/"),
+ error = erl_prim_loader:get_file(AbsArchiveFile ++ "/."),
+ {ok,Bin,AbsBeam} = erl_prim_loader:get_file(AbsBeam),
+ {ok,Bin,RelBeam} = erl_prim_loader:get_file(RelBeam),
+ {ok,Bin,DotSlashBeam} = erl_prim_loader:get_file(DotSlashBeam),
+
+ {ok,#file_info{type=directory}=DFI} =
+ erl_prim_loader:read_file_info(AbsArchiveFile),
+ {ok,DFI} = erl_prim_loader:read_file_info(RelArchiveFile),
+ {ok,DFI} = erl_prim_loader:read_file_info(DotSlashArchiveFile),
+ {ok,DFI} = erl_prim_loader:read_file_info(AbsArchiveFile ++ "/"),
+ {ok,DFI} = erl_prim_loader:read_file_info(AbsArchiveFile ++ "/."),
+ {ok,#file_info{type=regular}=RFI} = erl_prim_loader:read_file_info(AbsBeam),
+ {ok,RFI} = erl_prim_loader:read_file_info(RelBeam),
+ {ok,RFI} = erl_prim_loader:read_file_info(DotSlashBeam),
+
+ F = AbsArchiveFile ++ ".extension",
+ error = erl_prim_loader:list_dir(F),
+ {ok,_,_} = erl_prim_loader:get_file(F),
+ {ok,#file_info{type=regular}} = erl_prim_loader:read_file_info(F),
+
+ ok.