diff options
Diffstat (limited to 'erts')
-rw-r--r-- | erts/doc/src/erl_driver.xml | 10 | ||||
-rw-r--r-- | erts/doc/src/erl_nif.xml | 26 | ||||
-rw-r--r-- | erts/emulator/beam/dtrace-wrapper.h | 2 | ||||
-rw-r--r-- | erts/emulator/beam/erl_message.c | 4 | ||||
-rw-r--r-- | erts/emulator/beam/erl_process_lock.c | 2 | ||||
-rw-r--r-- | erts/emulator/drivers/common/efile_drv.c | 2 | ||||
-rw-r--r-- | erts/emulator/drivers/unix/unix_efile.c | 8 | ||||
-rw-r--r-- | erts/preloaded/ebin/erl_prim_loader.beam | bin | 52904 -> 54420 bytes | |||
-rw-r--r-- | erts/preloaded/src/erl_prim_loader.erl | 330 |
9 files changed, 225 insertions, 159 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 @@ <cref> <header> <copyright> - <year>2001</year><year>2011</year> + <year>2001</year><year>2012</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -1067,7 +1067,7 @@ typedef struct ErlIOVec { </desc> </func> <func> - <name><ret>ErlDrvBinary*</ret><nametext>driver_alloc_binary(ErlDrvSizeT size)</nametext></name> + <name><ret>ErlDrvBinary *</ret><nametext>driver_alloc_binary(ErlDrvSizeT size)</nametext></name> <fsummary>Allocate a driver binary</fsummary> <desc> <marker id="driver_alloc_binary"></marker> @@ -1087,7 +1087,7 @@ typedef struct ErlIOVec { </desc> </func> <func> - <name><ret>ErlDrvBinary*</ret><nametext>driver_realloc_binary(ErlDrvBinary *bin, ErlDrvSizeT size)</nametext></name> + <name><ret>ErlDrvBinary *</ret><nametext>driver_realloc_binary(ErlDrvBinary *bin, ErlDrvSizeT size)</nametext></name> <fsummary>Resize a driver binary</fsummary> <desc> <marker id="driver_realloc_binary"></marker> @@ -1277,7 +1277,7 @@ typedef struct ErlIOVec { </desc> </func> <func> - <name><ret>SysIOVec*</ret><nametext>driver_peekq(ErlDrvPort port, int *vlen)</nametext></name> + <name><ret>SysIOVec *</ret><nametext>driver_peekq(ErlDrvPort port, int *vlen)</nametext></name> <fsummary>Get the driver queue as a vector</fsummary> <desc> <marker id="driver_peekq"></marker> @@ -1481,7 +1481,7 @@ typedef struct ErlIOVec { </desc> </func> <func> - <name><ret>char*</ret><nametext>erl_errno_id(int error)</nametext></name> + <name><ret>char *</ret><nametext>erl_errno_id(int error)</nametext></name> <fsummary>Get erlang error atom name from error number</fsummary> <desc> <marker id="erl_errno_id"></marker> 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 @@ <cref> <header> <copyright> - <year>2001</year><year>2011</year> + <year>2001</year><year>2012</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -472,7 +472,7 @@ typedef enum { </section> <funcs> - <func><name><ret>void*</ret><nametext>enif_alloc(size_t size)</nametext></name> + <func><name><ret>void *</ret><nametext>enif_alloc(size_t size)</nametext></name> <fsummary>Allocate dynamic memory.</fsummary> <desc><p>Allocate memory of <c>size</c> bytes. Return NULL if allocation failed.</p></desc> </func> @@ -489,7 +489,7 @@ typedef enum { <p>Return true on success or false if allocation failed.</p> </desc> </func> - <func><name><ret>ErlNifEnv*</ret><nametext>enif_alloc_env()</nametext></name> + <func><name><ret>ErlNifEnv *</ret><nametext>enif_alloc_env()</nametext></name> <fsummary>Create a new environment</fsummary> <desc><p>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 { <p>Return pointer to the new environment.</p> </desc> </func> - <func><name><ret>void*</ret><nametext>enif_alloc_resource(ErlNifResourceType* type, unsigned size)</nametext></name> + <func><name><ret>void *</ret><nametext>enif_alloc_resource(ErlNifResourceType* type, unsigned size)</nametext></name> <fsummary>Allocate a memory managed resource object</fsummary> <desc><p>Allocate a memory managed resource object of type <c>type</c> and size <c>size</c> bytes.</p></desc> </func> @@ -522,7 +522,7 @@ typedef enum { <desc><p>Same as <seealso marker="erl_driver#erl_drv_cond_broadcast">erl_drv_cond_broadcast</seealso>. </p></desc> </func> - <func><name><ret>ErlNifCond*</ret><nametext>enif_cond_create(char *name)</nametext></name> + <func><name><ret>ErlNifCond *</ret><nametext>enif_cond_create(char *name)</nametext></name> <fsummary></fsummary> <desc><p>Same as <seealso marker="erl_driver#erl_drv_cond_create">erl_drv_cond_create</seealso>. </p></desc> @@ -840,7 +840,7 @@ typedef enum { <fsummary>Create an integer term from a long int</fsummary> <desc><p>Create an integer term from a <c>long int</c>.</p></desc> </func> - <func><name><ret>unsigned char*</ret><nametext>enif_make_new_binary(ErlNifEnv* env, size_t size, ERL_NIF_TERM* termp)</nametext></name> + <func><name><ret>unsigned char *</ret><nametext>enif_make_new_binary(ErlNifEnv* env, size_t size, ERL_NIF_TERM* termp)</nametext></name> <fsummary>Allocate and create a new binary term</fsummary> <desc><p>Allocate a binary of size <c>size</c> 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 { <fsummary>Create an integer term from an unsigned long int</fsummary> <desc><p>Create an integer term from an <c>unsigned long int</c>.</p></desc> </func> - <func><name><ret>ErlNifMutex*</ret><nametext>enif_mutex_create(char *name)</nametext></name> + <func><name><ret>ErlNifMutex *</ret><nametext>enif_mutex_create(char *name)</nametext></name> <fsummary></fsummary> <desc><p>Same as <seealso marker="erl_driver#erl_drv_mutex_create">erl_drv_mutex_create</seealso>. </p></desc> @@ -976,7 +976,7 @@ typedef enum { <desc><p>Same as <seealso marker="erl_driver#erl_drv_mutex_unlock">erl_drv_mutex_unlock</seealso>. </p></desc> </func> - <func><name><ret>ErlNifResourceType*</ret><nametext>enif_open_resource_type(ErlNifEnv* env, + <func><name><ret>ErlNifResourceType *</ret><nametext>enif_open_resource_type(ErlNifEnv* env, const char* module_str, const char* name, ErlNifResourceDtor* dtor, ErlNifResourceFlags flags, ErlNifResourceFlags* tried)</nametext></name> <fsummary>Create or takeover a resource type</fsummary> @@ -1005,7 +1005,7 @@ typedef enum { and <seealso marker="#upgrade">upgrade</seealso>.</p> </desc> </func> - <func><name><ret>void*</ret><nametext>enif_priv_data(ErlNifEnv* env)</nametext></name> + <func><name><ret>void *</ret><nametext>enif_priv_data(ErlNifEnv* env)</nametext></name> <fsummary>Get the private data of a NIF library</fsummary> <desc><p>Return the pointer to the private data that was set by <c>load</c>, <c>reload</c> or <c>upgrade</c>.</p> @@ -1033,7 +1033,7 @@ typedef enum { References made by <seealso marker="#enif_make_resource">enif_make_resource</seealso> can only be removed by the garbage collector.</p></desc> </func> - <func><name><ret>ErlNifRWLock*</ret><nametext>enif_rwlock_create(char *name)</nametext></name> + <func><name><ret>ErlNifRWLock *</ret><nametext>enif_rwlock_create(char *name)</nametext></name> <fsummary></fsummary> <desc><p>Same as <seealso marker="erl_driver#erl_drv_rwlock_create">erl_drv_rwlock_create</seealso>. </p></desc> @@ -1073,7 +1073,7 @@ typedef enum { <desc><p>Same as <seealso marker="erl_driver#erl_drv_rwlock_tryrwlock">erl_drv_rwlock_tryrwlock</seealso>. </p></desc> </func> - <func><name><ret>ErlNifPid*</ret><nametext>enif_self(ErlNifEnv* caller_env, ErlNifPid* pid)</nametext></name> + <func><name><ret>ErlNifPid *</ret><nametext>enif_self(ErlNifEnv* caller_env, ErlNifPid* pid)</nametext></name> <fsummary>Get the pid of the calling process.</fsummary> <desc><p>Initialize the pid variable <c>*pid</c> to represent the calling process. Return <c>pid</c>.</p></desc> @@ -1129,7 +1129,7 @@ typedef enum { <desc><p>Same as <seealso marker="erl_driver#erl_drv_thread_join">erl_drv_thread_join </seealso>. </p></desc> </func> - <func><name><ret>ErlNifThreadOpts*</ret><nametext>enif_thread_opts_create(char *name)</nametext></name> + <func><name><ret>ErlNifThreadOpts *</ret><nametext>enif_thread_opts_create(char *name)</nametext></name> <fsummary></fsummary> <desc><p>Same as <seealso marker="erl_driver#erl_drv_thread_opts_create">erl_drv_thread_opts_create</seealso>. </p></desc> @@ -1154,7 +1154,7 @@ typedef enum { <desc><p>Same as <seealso marker="erl_driver#erl_drv_tsd_key_destroy">erl_drv_tsd_key_destroy</seealso>. </p></desc> </func> - <func><name><ret>void*</ret><nametext>enif_tsd_get(ErlNifTSDKey key)</nametext></name> + <func><name><ret>void *</ret><nametext>enif_tsd_get(ErlNifTSDKey key)</nametext></name> <fsummary></fsummary> <desc><p>Same as <seealso marker="erl_driver#erl_drv_tsd_get">erl_drv_tsd_get</seealso>. </p></desc> diff --git a/erts/emulator/beam/dtrace-wrapper.h b/erts/emulator/beam/dtrace-wrapper.h index 1aeb7f9221..6ec0c91e21 100644 --- a/erts/emulator/beam/dtrace-wrapper.h +++ b/erts/emulator/beam/dtrace-wrapper.h @@ -42,6 +42,8 @@ #define DTRACE_CHARBUF(name, size) \ char name##_BUFFER[size], *name = name##_BUFFER +#define DTRACE_CHARBUF_NAME(name) name##_BUFFER + #if defined(USE_DYNAMIC_TRACE) && defined(USE_VM_PROBES) #include "erlang_dtrace.h" diff --git a/erts/emulator/beam/erl_message.c b/erts/emulator/beam/erl_message.c index 26bb015070..c98ca09f3f 100644 --- a/erts/emulator/beam/erl_message.c +++ b/erts/emulator/beam/erl_message.c @@ -888,8 +888,8 @@ erts_send_message(Process* sender, #ifdef USE_VM_PROBES *sender_name = *receiver_name = '\0'; if (DTRACE_ENABLED(message_send)) { - erts_snprintf(sender_name, sizeof(sender_name), "%T", sender->id); - erts_snprintf(receiver_name, sizeof(receiver_name), "%T", receiver->id); + erts_snprintf(sender_name, sizeof(DTRACE_CHARBUF_NAME(sender_name)), "%T", sender->id); + erts_snprintf(receiver_name, sizeof(DTRACE_CHARBUF_NAME(receiver_name)), "%T", receiver->id); } #endif if (SEQ_TRACE_TOKEN(sender) != NIL && !(flags & ERTS_SND_FLG_NO_SEQ_TRACE)) { diff --git a/erts/emulator/beam/erl_process_lock.c b/erts/emulator/beam/erl_process_lock.c index bae2b383a4..83272aab42 100644 --- a/erts/emulator/beam/erl_process_lock.c +++ b/erts/emulator/beam/erl_process_lock.c @@ -1272,7 +1272,7 @@ void erts_lcnt_enable_proc_lock_count(int enable) { int i; for (i = 0; i < erts_max_processes; ++i) { - Process* p = process_tab[i]; + Process* p = erts_pix2proc(i); if (p) { if (enable) { if (!ERTS_LCNT_LOCK_TYPE(&(p->lock.lcnt_main))) { diff --git a/erts/emulator/drivers/common/efile_drv.c b/erts/emulator/drivers/common/efile_drv.c index 603d1d47b6..347247ee7b 100644 --- a/erts/emulator/drivers/common/efile_drv.c +++ b/erts/emulator/drivers/common/efile_drv.c @@ -522,7 +522,7 @@ static void *ef_safe_alloc(Uint s) static void *ef_safe_realloc(void *op, Uint s) { void *p = EF_REALLOC(op, s); - if (!p) erl_exit(1, "efile drv: Can't reallocate %d bytes of memory\n", s); + if (!p) erl_exit(1, "efile drv: Can't reallocate %lu bytes of memory\n", (unsigned long)s); return p; } diff --git a/erts/emulator/drivers/unix/unix_efile.c b/erts/emulator/drivers/unix/unix_efile.c index ad112f7590..b250bac4dc 100644 --- a/erts/emulator/drivers/unix/unix_efile.c +++ b/erts/emulator/drivers/unix/unix_efile.c @@ -107,8 +107,8 @@ static void *ef_safe_alloc(Uint s) { void *p = EF_ALLOC(s); if (!p) erl_exit(1, - "unix efile drv: Can't allocate %d bytes of memory\n", - s); + "unix efile drv: Can't allocate %lu bytes of memory\n", + (unsigned long)s); return p; } @@ -118,8 +118,8 @@ static void *ef_safe_realloc(void *op, Uint s) { void *p = EF_REALLOC(op, s); if (!p) erl_exit(1, - "unix efile drv: Can't reallocate %d bytes of memory\n", - s); + "unix efile drv: Can't reallocate %lu bytes of memory\n", + (unsigned long)s); return p; } diff --git a/erts/preloaded/ebin/erl_prim_loader.beam b/erts/preloaded/ebin/erl_prim_loader.beam Binary files differindex 62d161850c..8e92cc21cb 100644 --- a/erts/preloaded/ebin/erl_prim_loader.beam +++ b/erts/preloaded/ebin/erl_prim_loader.beam diff --git a/erts/preloaded/src/erl_prim_loader.erl b/erts/preloaded/src/erl_prim_loader.erl index 14a7a2bf20..cd5519f537 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 @@ -49,7 +49,7 @@ prim_read_file_info/2, prim_get_cwd/2]). %% Used by escript and code --export([set_primary_archive/3, release_archives/0]). +-export([set_primary_archive/4, release_archives/0]). -include_lib("kernel/include/file.hrl"). @@ -222,15 +222,16 @@ get_cwd(Drive) -> check_file_result(get_cwd, Drive, request({get_cwd,[Drive]})). -spec set_primary_archive(File :: string() | 'undefined', - ArchiveBin :: binary() | 'undefined', - FileInfo :: #file_info{} | 'undefined') + ArchiveBin :: binary() | 'undefined', + FileInfo :: #file_info{} | 'undefined', + ParserFun :: fun()) -> {ok, [string()]} | {error,_}. -set_primary_archive(undefined, undefined, undefined) -> - request({set_primary_archive, undefined, undefined, undefined}); -set_primary_archive(File, ArchiveBin, FileInfo) +set_primary_archive(undefined, undefined, undefined, ParserFun) -> + request({set_primary_archive, undefined, undefined, undefined, ParserFun}); +set_primary_archive(File, ArchiveBin, FileInfo, ParserFun) when is_list(File), is_binary(ArchiveBin), is_record(FileInfo, file_info) -> - request({set_primary_archive, File, ArchiveBin, FileInfo}). + request({set_primary_archive, File, ArchiveBin, FileInfo, ParserFun}). -spec release_archives() -> 'ok' | {'error', _}. @@ -318,8 +319,11 @@ loop(State, Parent, Paths) -> {get_cwd,[_]=Args} -> {Res,State1} = handle_get_cwd(State, Args), {Res,State1,Paths}; - {set_primary_archive,File,Bin,FileInfo} -> - {Res,State1} = handle_set_primary_archive(State, File, Bin, FileInfo), + {set_primary_archive,File,ArchiveBin,FileInfo,ParserFun} -> + {Res,State1} = + handle_set_primary_archive(State, File, + ArchiveBin, FileInfo, + ParserFun), {Res,State1,Paths}; release_archives -> {Res,State1} = handle_release_archives(State), @@ -359,8 +363,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, FileInfo) -> - ?SAFE2(efile_set_primary_archive(State, File, Bin, FileInfo), State). +handle_set_primary_archive(State= #state{loader = efile}, File, ArchiveBin, FileInfo, ParserFun) -> + ?SAFE2(efile_set_primary_archive(State, File, ArchiveBin, FileInfo, ParserFun), State). handle_release_archives(State= #state{loader = efile}) -> ?SAFE2(efile_release_archives(State), State). @@ -484,8 +488,10 @@ 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, FileInfo) -> - {Res, PS2} = prim_set_primary_archive(PS, File, Bin, FileInfo), +efile_set_primary_archive(#state{prim_state = PS} = State, File, + ArchiveBin, FileInfo, ParserFun) -> + {Res, PS2} = prim_set_primary_archive(PS, File, ArchiveBin, + FileInfo, ParserFun), {Res,State#state{prim_state = PS2}}. efile_release_archives(#state{prim_state = PS} = State) -> @@ -791,7 +797,7 @@ prim_release_archives(PS) -> prim_do_release_archives(PS, [{ArchiveFile, DictVal} | KeyVals], Acc) -> Res = case DictVal of - {primary, _PrimZip, _FI} -> + {primary, _PrimZip, _FI, _ParserFun} -> ok; % Keep primary archive {Cache, _FI} -> debug(PS, {release, cache, ArchiveFile}), @@ -809,7 +815,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, undefined) -> +prim_set_primary_archive(PS, undefined, undefined, undefined, _ParserFun) -> debug(PS, {set_primary_archive, clean}), case PS#prim_state.primary_archive of undefined -> @@ -817,48 +823,40 @@ prim_set_primary_archive(PS, undefined, undefined, undefined) -> debug(PS, {return, Res}), {Res, PS}; ArchiveFile -> - {primary, PrimZip, _FI} = erase(ArchiveFile), + {primary, PrimZip, _FI, _ParserFun2} = 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, #file_info{} = FileInfo) - when is_list(ArchiveFile), is_binary(ArchiveBin) -> + +prim_set_primary_archive(PS, ArchiveFile0, ArchiveBin, + #file_info{} = FileInfo, ParserFun) + 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 -> - Fun = - fun({Funny, _GI, _GB}, A) -> - case Funny of - ["", "nibe", RevApp] -> % Reverse ebin - %% Collect ebin directories in archive - Ebin = reverse(RevApp) ++ "/ebin", - {true, [Ebin | A]}; - _ -> - {true, A} - end - end, - Ebins0 = [ArchiveFile], - case open_archive({ArchiveFile, ArchiveBin}, FileInfo, Ebins0, Fun) of - {ok, PrimZip, {RevEbins, FI, _}} -> - Ebins = reverse(RevEbins), + case load_prim_archive(ArchiveFile, ArchiveBin, FileInfo) of + {ok, PrimZip, FI, Ebins} -> debug(PS, {set_primary_archive, Ebins}), - put(ArchiveFile, {primary, PrimZip, FI}), - {{ok, Ebins}, PS#prim_state{primary_archive = ArchiveFile}}; + put(ArchiveFile, {primary, PrimZip, FI, ParserFun}), + {{ok, Ebins}, + PS#prim_state{primary_archive = ArchiveFile}}; Error -> debug(PS, {set_primary_archive, Error}), {Error, PS} end; OldArchiveFile -> debug(PS, {set_primary_archive, clean}), - {primary, PrimZip, _FI} = erase(OldArchiveFile), + {primary, PrimZip, _FI, _ParserFun} = erase(OldArchiveFile), ok = prim_zip:close(PrimZip), PS2 = PS#prim_state{primary_archive = undefined}, - prim_set_primary_archive(PS2, ArchiveFile, ArchiveBin, FileInfo) + prim_set_primary_archive(PS2, ArchiveFile, ArchiveBin, + FileInfo, ParserFun) end, debug(PS3, {return, Res3}), {Res3, PS3}. @@ -873,11 +871,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} @@ -900,11 +898,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 @@ -914,16 +912,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]}}; _ -> @@ -962,15 +960,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()}}; _ -> @@ -1011,7 +1008,7 @@ apply_archive(PS, Fun, Acc, Archive) -> %% put(Archive, {Error, FI}), {Error, PS} end; - {primary, PrimZip, FI} -> + {primary, PrimZip, FI, ParserFun} -> case prim_file:read_file_info(Archive) of {ok, FI2} when FI#file_info.mtime =:= FI2#file_info.mtime -> @@ -1022,6 +1019,16 @@ apply_archive(PS, Fun, Acc, Archive) -> debug(PS, {primary, Error}), {Error, PS} end; + {ok, FI2} -> + ok = clear_cache(Archive, {ok, PrimZip}), + case load_prim_archive(Archive, FI2, ParserFun) of + {ok, PrimZip2, FI3, _Ebins} -> + debug(PS, {cache, {update, Archive}}), + put(Archive, {primary, PrimZip2, FI3, ParserFun}); + Error2 -> + debug(PS, {cache, {clear, Error2}}) + end, + apply_archive(PS, Fun, Acc, Archive); Error -> debug(PS, {cache, {clear, Error}}), clear_cache(Archive, {ok, PrimZip}), @@ -1063,50 +1070,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 - [_ | FunnyDir] -> - case lists:member(FunnyDir, FunnyDirs) of % BIF +ensure_virtual_dirs(Components, Fun, FakeFI, Includes, Dirs, Acc) -> + case Components of + [_] -> + %% 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 -> - {reverse(Includes), FunnyDirs, Acc} - end; - [] -> - {reverse(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. 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). @@ -1202,15 +1228,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) -> @@ -1235,26 +1265,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 +1333,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 +1408,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 +1426,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 +1438,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 +1459,53 @@ 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). + +load_prim_archive(ArchiveFile, ArchiveBin, #file_info{}=FileInfo) -> + Fun = fun({Components, _GI, _GB}, A) -> + case Components of + ["", "nibe", RevApp] -> % Reverse ebin + %% Collect ebin directories in archive + Ebin = lists:reverse(RevApp, "/ebin"), + {true, [Ebin | A]}; + _ -> + {true, A} + end + end, + Ebins0 = [ArchiveFile], + case open_archive({ArchiveFile, ArchiveBin}, FileInfo, + Ebins0, Fun) of + {ok, PrimZip, {RevEbins, FI, _}} -> + Ebins = reverse(RevEbins), + {ok, PrimZip, FI, Ebins}; + Error -> + Error + end; +load_prim_archive(ArchiveFile, FileInfo, ParserFun) -> + case ParserFun(ArchiveFile) of + {ok, ArchiveBin} -> + load_prim_archive(ArchiveFile, ArchiveBin, FileInfo); + Error -> + Error + end. |