From e029c2d8920b356adfb71786c838f43f6b44f99a Mon Sep 17 00:00:00 2001
From: Siri Hansen
Date: Mon, 9 Jul 2012 15:30:48 +0200
Subject: Fix erl_prim_loader errors in handling of primary archive
The following errors have been corrected:
* 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 /full/path/to/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 has been removed.
Thanks to Tuncer Ayaz and Shunichi Shinohara for reporting and
co-authoring corrections.
---
erts/preloaded/src/erl_prim_loader.erl | 109 ++++++++++++++++++---------------
1 file changed, 58 insertions(+), 51 deletions(-)
diff --git a/erts/preloaded/src/erl_prim_loader.erl b/erts/preloaded/src/erl_prim_loader.erl
index 14a7a2bf20..f820d6226d 100644
--- a/erts/preloaded/src/erl_prim_loader.erl
+++ b/erts/preloaded/src/erl_prim_loader.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1996-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
@@ -824,10 +824,11 @@ prim_set_primary_archive(PS, undefined, undefined, undefined) ->
debug(PS2, {return, Res}),
{Res, PS2}
end;
-prim_set_primary_archive(PS, ArchiveFile, ArchiveBin, #file_info{} = FileInfo)
- when is_list(ArchiveFile), is_binary(ArchiveBin) ->
+prim_set_primary_archive(PS, ArchiveFile0, ArchiveBin, #file_info{} = FileInfo)
+ when is_list(ArchiveFile0), is_binary(ArchiveBin) ->
%% Try the archive file
- debug(PS, {set_primary_archive, ArchiveFile, byte_size(ArchiveBin)}),
+ debug(PS, {set_primary_archive, ArchiveFile0, byte_size(ArchiveBin)}),
+ ArchiveFile = absname(ArchiveFile0),
{Res3, PS3} =
case PS#prim_state.primary_archive of
undefined ->
@@ -1084,6 +1085,8 @@ open_archive(Archive, FileInfo, Acc, Fun) ->
ensure_virtual_dirs(Funny, Fun, FakeFI, Includes, FunnyDirs, Acc) ->
case Funny of
+ [_] ->
+ {Includes, FunnyDirs, Acc};
[_ | FunnyDir] ->
case lists:member(FunnyDir, FunnyDirs) of % BIF
false ->
@@ -1096,11 +1099,9 @@ ensure_virtual_dirs(Funny, Fun, FakeFI, Includes, FunnyDirs, Acc) ->
{_Continue, Acc3} = Fun({VirtualDir, GetInfo, GetBin}, Acc2),
{I, F, Acc3};
true ->
- {reverse(Includes), FunnyDirs, Acc}
- end;
- [] ->
- {reverse(Includes), FunnyDirs, Acc}
- end.
+ ensure_virtual_dirs(FunnyDir,Fun,FakeFI,Includes,FunnyDirs,Acc)
+ end
+ end.
foldl_archive(PrimZip, Acc, Fun) ->
Wrapper =
@@ -1235,26 +1236,22 @@ do_name_split(undefined, File) ->
%% False match. Assume plain file
{file, File}
end;
-do_name_split(ArchiveFile0, File) ->
+do_name_split(ArchiveFile, File) ->
%% Look first in primary archive
- ArchiveFile = absname(ArchiveFile0),
case string_match(File, ArchiveFile, []) of
no_match ->
%% Archive or plain file
do_name_split(undefined, File);
{match, _RevPrimArchiveFile, FileInArchive} ->
%% Primary archive
- case FileInArchive of
- [$/ | FileInArchive2] ->
- {archive, ArchiveFile, FileInArchive2};
- _ ->
- {archive, ArchiveFile, FileInArchive}
- end
+ {archive, ArchiveFile, FileInArchive}
end.
string_match([Char | File], [Char | Archive], RevTop) ->
string_match(File, Archive, [Char | RevTop]);
-string_match(File, [], RevTop) ->
+string_match([] = File, [], RevTop) ->
+ {match, RevTop, File};
+string_match([$/ | File], [], RevTop) ->
{match, RevTop, File};
string_match(_File, _Archive, _RevTop) ->
no_match.
@@ -1307,24 +1304,26 @@ ipv4_addr([], D, [C,B,A]) when D < 256 -> {A,B,C,D}.
%% A simplified version of filename:absname/1
absname(Name) ->
Name2 = normalize(Name, []),
- case pathtype(Name2) of
- absolute ->
- Name2;
- relative ->
- case prim_file:get_cwd() of
- {ok, Cwd} ->
- Cwd ++ "/" ++ Name2;
- {error, _} ->
- Name2
- end;
- volumerelative ->
- case prim_file:get_cwd() of
- {ok, Cwd} ->
- absname_vr(Name2, Cwd);
- {error, _} ->
- Name2
- end
- end.
+ Name3 =
+ case pathtype(Name2) of
+ absolute ->
+ Name2;
+ relative ->
+ case prim_file:get_cwd() of
+ {ok, Cwd} ->
+ Cwd ++ "/" ++ Name2;
+ {error, _} ->
+ Name2
+ end;
+ volumerelative ->
+ case prim_file:get_cwd() of
+ {ok, Cwd} ->
+ absname_vr(Name2, Cwd);
+ {error, _} ->
+ Name2
+ end
+ end,
+ path_flatten(Name3).
%% Assumes normalized name
absname_vr([$/ | NameRest], [Drive, $\: | _]) ->
@@ -1380,22 +1379,12 @@ win32_pathtype(Name) ->
win32_pathtype([Char | List++Rest]);
[$/, $/|_] ->
absolute;
- [$\\, $/|_] ->
- absolute;
- [$/, $\\|_] ->
- absolute;
- [$\\, $\\|_] ->
- absolute;
[$/|_] ->
volumerelative;
- [$\\|_] ->
- volumerelative;
[C1, C2, List | Rest] when is_list(List) ->
- pathtype([C1, C2|List ++ Rest]);
+ win32_pathtype([C1, C2|List ++ Rest]);
[_Letter, $:, $/|_] ->
absolute;
- [_Letter, $:, $\\|_] ->
- absolute;
[_Letter, $:|_] ->
volumerelative;
_ ->
@@ -1408,8 +1397,6 @@ vxworks_first(Name) ->
{not_device, [], []};
[$/ | T] ->
vxworks_first2(device, T, [$/]);
- [$\\ | T] ->
- vxworks_first2(device, T, [$/]);
[H | T] when is_list(H) ->
vxworks_first(H ++ T);
[H | T] ->
@@ -1422,8 +1409,6 @@ vxworks_first2(Devicep, Name, FirstComp) ->
{Devicep, [], FirstComp};
[$/ |T ] ->
{Devicep, [$/ | T], FirstComp};
- [$\\ | T] ->
- {Devicep, [$/ | T], FirstComp};
[$: | T]->
{device, T, [$: | FirstComp]};
[H | T] when is_list(H) ->
@@ -1445,3 +1430,25 @@ normalize(Name, Acc) ->
[] ->
reverse(Acc)
end.
+
+%% Remove .. and . from the path, e.g.
+%% /path/./to/this/../file -> /path/to/file
+path_flatten(Name) ->
+ path_flatten(Name,[],[]).
+
+path_flatten([$/,$.,$.,$/|Rest],_RevLast,RevTop) ->
+ path_flatten(Rest,[],RevTop);
+path_flatten([$/,$.,$/|Rest],RevLast,RevTop) ->
+ path_flatten([$/|Rest],RevLast,RevTop);
+path_flatten([$/,$.,$.],_RevLast,RevTop) ->
+ path_flatten([],[],RevTop);
+path_flatten([$/,$.],RevLast,RevTop) ->
+ path_flatten([],RevLast,RevTop);
+path_flatten([$/],RevLast,RevTop) ->
+ path_flatten([],RevLast,RevTop);
+path_flatten([$/|Rest],RevLast,RevTop) ->
+ path_flatten(Rest,[],[$/|RevLast++RevTop]);
+path_flatten([Ch|Rest],RevLast,RevTop) ->
+ path_flatten(Rest,[Ch|RevLast],RevTop);
+path_flatten([],RevLast,RevTop) ->
+ reverse(RevLast++RevTop).
--
cgit v1.2.3
From 13d135515cabfe4e741a4350cfe294e041c06158 Mon Sep 17 00:00:00 2001
From: Siri Hansen
Date: Mon, 9 Jul 2012 16:21:57 +0200
Subject: Add comments to make erl_prim_loader primary archive handling more
readable
This commit introduces no functional change. It only adds comments and
changes some function/variable names.
---
erts/preloaded/src/erl_prim_loader.erl | 126 +++++++++++++++++++--------------
1 file changed, 74 insertions(+), 52 deletions(-)
diff --git a/erts/preloaded/src/erl_prim_loader.erl b/erts/preloaded/src/erl_prim_loader.erl
index f820d6226d..eb59cbe6f6 100644
--- a/erts/preloaded/src/erl_prim_loader.erl
+++ b/erts/preloaded/src/erl_prim_loader.erl
@@ -833,8 +833,8 @@ prim_set_primary_archive(PS, ArchiveFile0, ArchiveBin, #file_info{} = FileInfo)
case PS#prim_state.primary_archive of
undefined ->
Fun =
- fun({Funny, _GI, _GB}, A) ->
- case Funny of
+ fun({Components, _GI, _GB}, A) ->
+ case Components of
["", "nibe", RevApp] -> % Reverse ebin
%% Collect ebin directories in archive
Ebin = reverse(RevApp) ++ "/ebin",
@@ -874,11 +874,11 @@ prim_get_file(PS, File) ->
{Res, PS};
{archive, ArchiveFile, FileInArchive} ->
debug(PS, {archive_get_file, ArchiveFile, FileInArchive}),
- FunnyFile = funny_split(FileInArchive, $/),
+ FileComponents = path_split(FileInArchive),
Fun =
- fun({Funny, _GetInfo, GetBin}, Acc) ->
+ fun({Components, _GetInfo, GetBin}, Acc) ->
if
- Funny =:= FunnyFile ->
+ Components =:= FileComponents ->
{false, {ok, GetBin()}};
true ->
{true, Acc}
@@ -901,11 +901,11 @@ prim_list_dir(PS, Dir) ->
{Res, PS};
{archive, ArchiveFile, FileInArchive} ->
debug(PS, {archive_list_dir, ArchiveFile, FileInArchive}),
- FunnyDir = funny_split(FileInArchive, $/),
+ DirComponents = path_split(FileInArchive),
Fun =
- fun({Funny, _GetInfo, _GetBin}, {Status, Names} = Acc) ->
- case Funny of
- [RevName | FD] when FD =:= FunnyDir ->
+ fun({Components, _GetInfo, _GetBin}, {Status, Names} = Acc) ->
+ case Components of
+ [RevName | DC] when DC =:= DirComponents ->
case RevName of
"" ->
%% The listed directory
@@ -915,16 +915,16 @@ prim_list_dir(PS, Dir) ->
Name = reverse(RevName),
{true, {Status, [Name | Names]}}
end;
- ["", RevName | FD] when FD =:= FunnyDir ->
+ ["", RevName | DC] when DC =:= DirComponents ->
%% Directory
Name = reverse(RevName),
{true, {Status, [Name | Names]}};
- [RevName] when FunnyDir =:= [""] ->
- %% Top file
+ [RevName] when DirComponents =:= [""] ->
+ %% File in top directory
Name = reverse(RevName),
{true, {ok, [Name | Names]}};
- ["", RevName] when FunnyDir =:= [""] ->
- %% Top file
+ ["", RevName] when DirComponents =:= [""] ->
+ %% Directory in top directory
Name = reverse(RevName),
{true, {ok, [Name | Names]}};
_ ->
@@ -963,15 +963,14 @@ prim_read_file_info(PS, File) ->
end;
{archive, ArchiveFile, FileInArchive} ->
debug(PS, {archive_read_file_info, File}),
- FunnyFile = funny_split(FileInArchive, $/),
+ FileComponents = path_split(FileInArchive),
Fun =
- fun({Funny, GetInfo, _GetBin}, Acc) ->
- case Funny of
- [H | T] when H =:= "",
- T =:= FunnyFile ->
+ fun({Components, GetInfo, _GetBin}, Acc) ->
+ case Components of
+ ["" | F] when F =:= FileComponents ->
%% Directory
{false, {ok, GetInfo()}};
- F when F =:= FunnyFile ->
+ F when F =:= FileComponents ->
%% Plain file
{false, {ok, GetInfo()}};
_ ->
@@ -1064,50 +1063,69 @@ open_archive(Archive, Acc, Fun) ->
{error, Reason}
end.
+%% Open the given archive and iterate through all files with an own
+%% wrapper fun in order to identify each file as a component list as
+%% returned from path_split/1.
+%%
+%% In the archive (zip) file, directory elements might or might not be
+%% present. To ensure consistency, a directory element is added if it
+%% does not already exist (ensure_virual_dir/6). NOTE that there will
+%% be no such directory element for the top directory of the archive.
open_archive(Archive, FileInfo, Acc, Fun) ->
FakeFI = FileInfo#file_info{type = directory},
Wrapper =
- fun({N, GI, GB}, {A, I, FunnyDirs}) -> % Full iteration at open
- Funny = funny_split(N, $/),
- FunnyDirs2 =
- case Funny of
- ["" | FunnyDir] ->
- [FunnyDir | FunnyDirs];
+ fun({N, GI, GB}, {A, I, Dirs}) ->
+ Components = path_split(N),
+ Dirs2 =
+ case Components of
+ ["" | Dir] ->
+ %% This is a directory
+ [Dir | Dirs];
_ ->
- FunnyDirs
+ %% This is a regular file
+ Dirs
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}}
+ {Includes, Dirs3, A2} =
+ ensure_virtual_dirs(Components, Fun, FakeFI,
+ [{true, Components}], Dirs2, A),
+ {_Continue, A3} = Fun({Components, GI, GB}, A2),
+ {true, Includes, {A3, I, Dirs3}}
end,
prim_zip:open(Wrapper, {Acc, FakeFI, []}, Archive).
-ensure_virtual_dirs(Funny, Fun, FakeFI, Includes, FunnyDirs, Acc) ->
- case Funny of
+ensure_virtual_dirs(Components, Fun, FakeFI, Includes, Dirs, Acc) ->
+ case Components of
[_] ->
- {Includes, FunnyDirs, Acc};
- [_ | FunnyDir] ->
- case lists:member(FunnyDir, FunnyDirs) of % BIF
+ %% Don't add virtual dir for top directory
+ {Includes, Dirs, Acc};
+ [_ | Dir] ->
+ case lists:member(Dir, Dirs) of % BIF
false ->
+ %% The directory does not yet exist - add it
GetInfo = fun() -> FakeFI end,
GetBin = fun() -> <<>> end,
- VirtualDir = ["" | FunnyDir],
+ VirtualDir = ["" | Dir],
Includes2 = [{true, VirtualDir, GetInfo, GetBin} | Includes],
- FunnyDirs2 = [FunnyDir | FunnyDirs],
- {I, F, Acc2} = ensure_virtual_dirs(FunnyDir, Fun, FakeFI, Includes2, FunnyDirs2, Acc),
+ Dirs2 = [Dir | Dirs],
+
+ %% Recursively ensure dir elements on all levels
+ {I, F, Acc2} = ensure_virtual_dirs(Dir, Fun, FakeFI,
+ Includes2, Dirs2, Acc),
+
{_Continue, Acc3} = Fun({VirtualDir, GetInfo, GetBin}, Acc2),
{I, F, Acc3};
true ->
- ensure_virtual_dirs(FunnyDir,Fun,FakeFI,Includes,FunnyDirs,Acc)
+ %% The directory element does already exist
+ %% Recursivly ensure dir elements on all levels
+ ensure_virtual_dirs(Dir,Fun,FakeFI,Includes,Dirs,Acc)
end
- end.
+ end.
foldl_archive(PrimZip, Acc, Fun) ->
Wrapper =
- fun({Funny, GI, GB}, A) ->
+ fun({Components, GI, GB}, A) ->
%% Allow partial iteration at foldl
- {Continue, A2} = Fun({Funny, GI, GB}, A),
+ {Continue, A2} = Fun({Components, GI, GB}, A),
{Continue, true, A2}
end,
prim_zip:foldl(Wrapper, Acc, PrimZip).
@@ -1203,15 +1221,19 @@ reverse([A, B]) ->
reverse([A, B | L]) ->
lists:reverse(L, [B, A]). % BIF
-%% Returns all lists in reverse order
-funny_split(List, Sep) ->
- funny_split(List, Sep, [], []).
-
-funny_split([Sep | Tail], Sep, Path, Paths) ->
- funny_split(Tail, Sep, [], [Path | Paths]);
-funny_split([Head | Tail], Sep, Path, Paths) ->
- funny_split(Tail, Sep, [Head | Path], Paths);
-funny_split([], _Sep, Path, Paths) ->
+%% Returns a reversed list of path components, each component itself a
+%% reversed list (string), e.g.
+%% /path/to/file -> ["elif","ot","htap",""]
+%% /path/to/dir/ -> ["","rid","ot","htap",""]
+%% Note the "" marking leading and trailing / (slash).
+path_split(List) ->
+ path_split(List, [], []).
+
+path_split([$/ | Tail], Path, Paths) ->
+ path_split(Tail, [], [Path | Paths]);
+path_split([Head | Tail], Path, Paths) ->
+ path_split(Tail, [Head | Path], Paths);
+path_split([], Path, Paths) ->
[Path | Paths].
name_split(ArchiveFile, File0) ->
--
cgit v1.2.3
From fc241fdbfacdca72f219a601ed16fb9cb6159063 Mon Sep 17 00:00:00 2001
From: Siri Hansen
Date: Mon, 9 Jul 2012 18:05:09 +0200
Subject: Add tests for problems with handling of primary archive
Thanks to Tuncer Ayaz for co-authoring.
---
lib/stdlib/test/escript_SUITE.erl | 126 ++++++++++++++++++++-
.../archive_script_file_access.erl | 86 ++++++++++++++
2 files changed, 210 insertions(+), 2 deletions(-)
create mode 100644 lib/stdlib/test/escript_SUITE_data/archive_script_file_access/archive_script_file_access.erl
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
+ %% "./":
+ %% 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 "./"
+ 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 "./"
+ 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.
--
cgit v1.2.3
From 4a79bc79e0ff4b39fc28b0f9ac154e8070534e21 Mon Sep 17 00:00:00 2001
From: Siri Hansen
Date: Mon, 9 Jul 2012 18:19:18 +0200
Subject: Update preloaded
erl_prim_loader.beam
---
erts/preloaded/ebin/erl_prim_loader.beam | Bin 52904 -> 53320 bytes
1 file changed, 0 insertions(+), 0 deletions(-)
diff --git a/erts/preloaded/ebin/erl_prim_loader.beam b/erts/preloaded/ebin/erl_prim_loader.beam
index df1831f340..8c6cc1100d 100644
Binary files a/erts/preloaded/ebin/erl_prim_loader.beam and b/erts/preloaded/ebin/erl_prim_loader.beam differ
--
cgit v1.2.3
From fcf0e43a4fe06fc3f44fbff96ee42378a479d35f Mon Sep 17 00:00:00 2001
From: Hans Bolinder
Date: Thu, 5 Jul 2012 10:19:00 +0200
Subject: Fix a bug regarding spaces in C function prototypes
Thanks to Richard O'Keefe for pointing the bug out.
---
lib/erl_docgen/priv/xsl/db_html.xsl | 21 ++++++++++++++++++++-
lib/erl_docgen/priv/xsl/db_man.xsl | 26 ++++++++++++++++++++++++--
lib/erl_docgen/priv/xsl/db_pdf.xsl | 20 ++++++++++++++++++--
3 files changed, 62 insertions(+), 5 deletions(-)
diff --git a/lib/erl_docgen/priv/xsl/db_html.xsl b/lib/erl_docgen/priv/xsl/db_html.xsl
index 7cf5465f90..4bc5abb364 100644
--- a/lib/erl_docgen/priv/xsl/db_html.xsl
+++ b/lib/erl_docgen/priv/xsl/db_html.xsl
@@ -1817,7 +1817,14 @@
-
+
+
+
+
+
+
+
+
@@ -1845,6 +1852,18 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/lib/erl_docgen/priv/xsl/db_man.xsl b/lib/erl_docgen/priv/xsl/db_man.xsl
index 5234ba6bd0..33808859c7 100644
--- a/lib/erl_docgen/priv/xsl/db_man.xsl
+++ b/lib/erl_docgen/priv/xsl/db_man.xsl
@@ -3,7 +3,7 @@
#
# %CopyrightBegin%
#
- # Copyright Ericsson AB 2009-2011. All Rights Reserved.
+ # Copyright Ericsson AB 2009-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
@@ -758,10 +758,32 @@
.B
-
+
+
+
+
+
+
+
+
+
+
+
+
.br
+
+
+
+
+
+
+
+
+
+
diff --git a/lib/erl_docgen/priv/xsl/db_pdf.xsl b/lib/erl_docgen/priv/xsl/db_pdf.xsl
index bf17406d84..da96052462 100644
--- a/lib/erl_docgen/priv/xsl/db_pdf.xsl
+++ b/lib/erl_docgen/priv/xsl/db_pdf.xsl
@@ -3,7 +3,7 @@
#
# %CopyrightBegin%
#
- # Copyright Ericsson AB 2009-2011. All Rights Reserved.
+ # Copyright Ericsson AB 2009-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
@@ -1424,7 +1424,13 @@
-
+
+
+
+
+
+
+
@@ -1432,6 +1438,16 @@
+
+
+
+
+
+
+
+
+
--
cgit v1.2.3
From fe1ce64f4c0fdbc05e7dae1234eb1a878bb2cc99 Mon Sep 17 00:00:00 2001
From: Hans Bolinder
Date: Mon, 9 Jul 2012 12:34:08 +0200
Subject: ic: add space before '*' in some function prototypes
---
lib/ic/doc/src/ic_clib.xml | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/lib/ic/doc/src/ic_clib.xml b/lib/ic/doc/src/ic_clib.xml
index b557c4b5f6..ebeaabae91 100644
--- a/lib/ic/doc/src/ic_clib.xml
+++ b/lib/ic/doc/src/ic_clib.xml
@@ -4,7 +4,7 @@
- 20032009
+ 20032012
Ericsson AB. All Rights Reserved.
@@ -41,7 +41,7 @@
- CORBA_Environment*CORBA_Environment_alloc(int inbufsz, int outbufsz)
+ CORBA_Environment *CORBA_Environment_alloc(int inbufsz, int outbufsz)
Allocate environment data.
This function is used to allocate and initiate the
@@ -79,14 +79,14 @@
- CORBA_char*CORBA_string_alloc(CORBA_unsigned_long len)
+ CORBA_char *CORBA_string_alloc(CORBA_unsigned_long len)
Allocate a string.
Allocates a (simple) CORBA character string of length len + 1.
- CORBA_wchar*CORBA_wstring_alloc(CORBA_unsigned_long len)
+ CORBA_wchar *CORBA_wstring_alloc(CORBA_unsigned_long len)
Allocate a wide string.
Allocates a CORBA wide string of length len + 1.
@@ -101,7 +101,7 @@
- CORBA_char*CORBA_exception_id(CORBA_Environment *env)
+ CORBA_char *CORBA_exception_id(CORBA_Environment *env)
Get exception identity.
Returns the exception identity if an exception is set, otherwise
@@ -109,7 +109,7 @@
- void*CORBA_exception_value(CORBA_Environment *env)
+ void *CORBA_exception_value(CORBA_Environment *env)
Get exception value.
Returns the exception value, if an exception is set, otherwise
@@ -160,7 +160,7 @@
- oe_map_t*oe_merge_maps(oe_map_t *maps, int size)
+ oe_map_t *oe_merge_maps(oe_map_t *maps, int size)
Merge an array of server maps to one single map.
Merge an array of server maps to one single map.
--
cgit v1.2.3
From 23307be619f0768d84464d13d94c8180d806ec49 Mon Sep 17 00:00:00 2001
From: Hans Bolinder
Date: Mon, 9 Jul 2012 12:38:00 +0200
Subject: erts: add space before '*' in some function prototypes
---
erts/doc/src/erl_driver.xml | 10 +++++-----
erts/doc/src/erl_nif.xml | 26 +++++++++++++-------------
2 files changed, 18 insertions(+), 18 deletions(-)
diff --git a/erts/doc/src/erl_driver.xml b/erts/doc/src/erl_driver.xml
index 4fd74b783e..187c263b60 100644
--- a/erts/doc/src/erl_driver.xml
+++ b/erts/doc/src/erl_driver.xml
@@ -4,7 +4,7 @@
- 20012011
+ 20012012
Ericsson AB. All Rights Reserved.
@@ -1067,7 +1067,7 @@ typedef struct ErlIOVec {
- ErlDrvBinary*driver_alloc_binary(ErlDrvSizeT size)
+ ErlDrvBinary *driver_alloc_binary(ErlDrvSizeT size)
Allocate a driver binary
@@ -1087,7 +1087,7 @@ typedef struct ErlIOVec {
- ErlDrvBinary*driver_realloc_binary(ErlDrvBinary *bin, ErlDrvSizeT size)
+ ErlDrvBinary *driver_realloc_binary(ErlDrvBinary *bin, ErlDrvSizeT size)
Resize a driver binary
@@ -1277,7 +1277,7 @@ typedef struct ErlIOVec {
- SysIOVec*driver_peekq(ErlDrvPort port, int *vlen)
+ SysIOVec *driver_peekq(ErlDrvPort port, int *vlen)
Get the driver queue as a vector
@@ -1481,7 +1481,7 @@ typedef struct ErlIOVec {
- char*erl_errno_id(int error)
+ char *erl_errno_id(int error)
Get erlang error atom name from error number
diff --git a/erts/doc/src/erl_nif.xml b/erts/doc/src/erl_nif.xml
index 5fc6508aad..f484e9eaf7 100644
--- a/erts/doc/src/erl_nif.xml
+++ b/erts/doc/src/erl_nif.xml
@@ -4,7 +4,7 @@
- 20012011
+ 20012012
Ericsson AB. All Rights Reserved.
@@ -472,7 +472,7 @@ typedef enum {
- void*enif_alloc(size_t size)
+ void *enif_alloc(size_t size)
Allocate dynamic memory.
Allocate memory of size bytes. Return NULL if allocation failed.
@@ -489,7 +489,7 @@ typedef enum {
Return true on success or false if allocation failed.
- ErlNifEnv*enif_alloc_env()
+ ErlNifEnv *enif_alloc_env()
Create a new environment
Allocate a new process independent environment. The environment can
be used to hold terms that is not bound to any process. Such terms can
@@ -499,7 +499,7 @@ typedef enum {
Return pointer to the new environment.
- void*enif_alloc_resource(ErlNifResourceType* type, unsigned size)
+ void *enif_alloc_resource(ErlNifResourceType* type, unsigned size)
Allocate a memory managed resource object
Allocate a memory managed resource object of type type and size size bytes.
@@ -522,7 +522,7 @@ typedef enum {
Same as erl_drv_cond_broadcast.
- ErlNifCond*enif_cond_create(char *name)
+ ErlNifCond *enif_cond_create(char *name)
Same as erl_drv_cond_create.
@@ -840,7 +840,7 @@ typedef enum {
Create an integer term from a long int
Create an integer term from a long int.
- unsigned char*enif_make_new_binary(ErlNifEnv* env, size_t size, ERL_NIF_TERM* termp)
+ unsigned char *enif_make_new_binary(ErlNifEnv* env, size_t size, ERL_NIF_TERM* termp)
Allocate and create a new binary term
Allocate a binary of size size bytes and create an owning
term. The binary data is mutable until the calling NIF returns. This is a
@@ -951,7 +951,7 @@ typedef enum {
Create an integer term from an unsigned long int
Create an integer term from an unsigned long int.
- ErlNifMutex*enif_mutex_create(char *name)
+ ErlNifMutex *enif_mutex_create(char *name)
Same as erl_drv_mutex_create.
@@ -976,7 +976,7 @@ typedef enum {
Same as erl_drv_mutex_unlock.
- ErlNifResourceType*enif_open_resource_type(ErlNifEnv* env,
+ ErlNifResourceType *enif_open_resource_type(ErlNifEnv* env,
const char* module_str, const char* name,
ErlNifResourceDtor* dtor, ErlNifResourceFlags flags, ErlNifResourceFlags* tried)
Create or takeover a resource type
@@ -1005,7 +1005,7 @@ typedef enum {
and upgrade.
- void*enif_priv_data(ErlNifEnv* env)
+ void *enif_priv_data(ErlNifEnv* env)
Get the private data of a NIF library
Return the pointer to the private data that was set by load,
reload or upgrade.
@@ -1033,7 +1033,7 @@ typedef enum {
References made by enif_make_resource
can only be removed by the garbage collector.
- ErlNifRWLock*enif_rwlock_create(char *name)
+ ErlNifRWLock *enif_rwlock_create(char *name)
Same as erl_drv_rwlock_create.
@@ -1073,7 +1073,7 @@ typedef enum {
Same as erl_drv_rwlock_tryrwlock.
- ErlNifPid*enif_self(ErlNifEnv* caller_env, ErlNifPid* pid)
+ ErlNifPid *enif_self(ErlNifEnv* caller_env, ErlNifPid* pid)
Get the pid of the calling process.
Initialize the pid variable *pid to represent the
calling process. Return pid.
@@ -1129,7 +1129,7 @@ typedef enum {
Same as erl_drv_thread_join .
- ErlNifThreadOpts*enif_thread_opts_create(char *name)
+ ErlNifThreadOpts *enif_thread_opts_create(char *name)
Same as erl_drv_thread_opts_create.
@@ -1154,7 +1154,7 @@ typedef enum {
Same as erl_drv_tsd_key_destroy.
- void*enif_tsd_get(ErlNifTSDKey key)
+ void *enif_tsd_get(ErlNifTSDKey key)
Same as erl_drv_tsd_get.
--
cgit v1.2.3