diff options
Diffstat (limited to 'src/rabbit_file.erl')
-rw-r--r-- | src/rabbit_file.erl | 307 |
1 files changed, 0 insertions, 307 deletions
diff --git a/src/rabbit_file.erl b/src/rabbit_file.erl deleted file mode 100644 index 81a617a8..00000000 --- a/src/rabbit_file.erl +++ /dev/null @@ -1,307 +0,0 @@ -%% The contents of this file are subject to the Mozilla Public License -%% Version 1.1 (the "License"); you may not use this file except in -%% compliance with the License. You may obtain a copy of the License -%% at http://www.mozilla.org/MPL/ -%% -%% 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. -%% -%% The Original Code is RabbitMQ. -%% -%% The Initial Developer of the Original Code is GoPivotal, Inc. -%% Copyright (c) 2011-2014 GoPivotal, Inc. All rights reserved. -%% - --module(rabbit_file). - --include_lib("kernel/include/file.hrl"). - --export([is_file/1, is_dir/1, file_size/1, ensure_dir/1, wildcard/2, list_dir/1]). --export([read_term_file/1, write_term_file/2, write_file/2, write_file/3]). --export([append_file/2, ensure_parent_dirs_exist/1]). --export([rename/2, delete/1, recursive_delete/1, recursive_copy/2]). --export([lock_file/1]). - --import(file_handle_cache, [with_handle/1, with_handle/2]). - --define(TMP_EXT, ".tmp"). - -%%---------------------------------------------------------------------------- - --ifdef(use_specs). - --type(ok_or_error() :: rabbit_types:ok_or_error(any())). - --spec(is_file/1 :: ((file:filename())) -> boolean()). --spec(is_dir/1 :: ((file:filename())) -> boolean()). --spec(file_size/1 :: ((file:filename())) -> non_neg_integer()). --spec(ensure_dir/1 :: ((file:filename())) -> ok_or_error()). --spec(wildcard/2 :: (string(), file:filename()) -> [file:filename()]). --spec(list_dir/1 :: (file:filename()) -> rabbit_types:ok_or_error2( - [file:filename()], any())). --spec(read_term_file/1 :: - (file:filename()) -> {'ok', [any()]} | rabbit_types:error(any())). --spec(write_term_file/2 :: (file:filename(), [any()]) -> ok_or_error()). --spec(write_file/2 :: (file:filename(), iodata()) -> ok_or_error()). --spec(write_file/3 :: (file:filename(), iodata(), [any()]) -> ok_or_error()). --spec(append_file/2 :: (file:filename(), string()) -> ok_or_error()). --spec(ensure_parent_dirs_exist/1 :: (string()) -> 'ok'). --spec(rename/2 :: - (file:filename(), file:filename()) -> ok_or_error()). --spec(delete/1 :: ([file:filename()]) -> ok_or_error()). --spec(recursive_delete/1 :: - ([file:filename()]) - -> rabbit_types:ok_or_error({file:filename(), any()})). --spec(recursive_copy/2 :: - (file:filename(), file:filename()) - -> rabbit_types:ok_or_error({file:filename(), file:filename(), any()})). --spec(lock_file/1 :: (file:filename()) -> rabbit_types:ok_or_error('eexist')). - --endif. - -%%---------------------------------------------------------------------------- - -is_file(File) -> - case read_file_info(File) of - {ok, #file_info{type=regular}} -> true; - {ok, #file_info{type=directory}} -> true; - _ -> false - end. - -is_dir(Dir) -> is_dir_internal(read_file_info(Dir)). - -is_dir_no_handle(Dir) -> is_dir_internal(prim_file:read_file_info(Dir)). - -is_dir_internal({ok, #file_info{type=directory}}) -> true; -is_dir_internal(_) -> false. - -file_size(File) -> - case read_file_info(File) of - {ok, #file_info{size=Size}} -> Size; - _ -> 0 - end. - -ensure_dir(File) -> with_handle(fun () -> ensure_dir_internal(File) end). - -ensure_dir_internal("/") -> - ok; -ensure_dir_internal(File) -> - Dir = filename:dirname(File), - case is_dir_no_handle(Dir) of - true -> ok; - false -> ensure_dir_internal(Dir), - prim_file:make_dir(Dir) - end. - -wildcard(Pattern, Dir) -> - case list_dir(Dir) of - {ok, Files} -> {ok, RE} = re:compile(Pattern, [anchored]), - [File || File <- Files, - match =:= re:run(File, RE, [{capture, none}])]; - {error, _} -> [] - end. - -list_dir(Dir) -> with_handle(fun () -> prim_file:list_dir(Dir) end). - -read_file_info(File) -> - with_handle(fun () -> prim_file:read_file_info(File) end). - -read_term_file(File) -> - try - {ok, Data} = with_handle(fun () -> prim_file:read_file(File) end), - {ok, Tokens, _} = erl_scan:string(binary_to_list(Data)), - TokenGroups = group_tokens(Tokens), - {ok, [begin - {ok, Term} = erl_parse:parse_term(Tokens1), - Term - end || Tokens1 <- TokenGroups]} - catch - error:{badmatch, Error} -> Error - end. - -group_tokens(Ts) -> [lists:reverse(G) || G <- group_tokens([], Ts)]. - -group_tokens([], []) -> []; -group_tokens(Cur, []) -> [Cur]; -group_tokens(Cur, [T = {dot, _} | Ts]) -> [[T | Cur] | group_tokens([], Ts)]; -group_tokens(Cur, [T | Ts]) -> group_tokens([T | Cur], Ts). - -write_term_file(File, Terms) -> - write_file(File, list_to_binary([io_lib:format("~w.~n", [Term]) || - Term <- Terms])). - -write_file(Path, Data) -> write_file(Path, Data, []). - -write_file(Path, Data, Modes) -> - Modes1 = [binary, write | (Modes -- [binary, write])], - case make_binary(Data) of - Bin when is_binary(Bin) -> write_file1(Path, Bin, Modes1); - {error, _} = E -> E - end. - -%% make_binary/1 is based on the corresponding function in the -%% kernel/file.erl module of the Erlang R14B02 release, which is -%% licensed under the EPL. - -make_binary(Bin) when is_binary(Bin) -> - Bin; -make_binary(List) -> - try - iolist_to_binary(List) - catch error:Reason -> - {error, Reason} - end. - -write_file1(Path, Bin, Modes) -> - try - with_synced_copy(Path, Modes, - fun (Hdl) -> - ok = prim_file:write(Hdl, Bin) - end) - catch - error:{badmatch, Error} -> Error; - _:{error, Error} -> {error, Error} - end. - -with_synced_copy(Path, Modes, Fun) -> - case lists:member(append, Modes) of - true -> - {error, append_not_supported, Path}; - false -> - with_handle( - fun () -> - Bak = Path ++ ?TMP_EXT, - case prim_file:open(Bak, Modes) of - {ok, Hdl} -> - try - Result = Fun(Hdl), - ok = prim_file:sync(Hdl), - ok = prim_file:rename(Bak, Path), - Result - after - prim_file:close(Hdl) - end; - {error, _} = E -> E - end - end) - end. - -%% TODO the semantics of this function are rather odd. But see bug 25021. -append_file(File, Suffix) -> - case read_file_info(File) of - {ok, FInfo} -> append_file(File, FInfo#file_info.size, Suffix); - {error, enoent} -> append_file(File, 0, Suffix); - Error -> Error - end. - -append_file(_, _, "") -> - ok; -append_file(File, 0, Suffix) -> - with_handle(fun () -> - case prim_file:open([File, Suffix], [append]) of - {ok, Fd} -> prim_file:close(Fd); - Error -> Error - end - end); -append_file(File, _, Suffix) -> - case with_handle(2, fun () -> - file:copy(File, {[File, Suffix], [append]}) - end) of - {ok, _BytesCopied} -> ok; - Error -> Error - end. - -ensure_parent_dirs_exist(Filename) -> - case ensure_dir(Filename) of - ok -> ok; - {error, Reason} -> - throw({error, {cannot_create_parent_dirs, Filename, Reason}}) - end. - -rename(Old, New) -> with_handle(fun () -> prim_file:rename(Old, New) end). - -delete(File) -> with_handle(fun () -> prim_file:delete(File) end). - -recursive_delete(Files) -> - with_handle( - fun () -> lists:foldl(fun (Path, ok) -> recursive_delete1(Path); - (_Path, {error, _Err} = Error) -> Error - end, ok, Files) - end). - -recursive_delete1(Path) -> - case is_dir_no_handle(Path) and not(is_symlink_no_handle(Path)) of - false -> case prim_file:delete(Path) of - ok -> ok; - {error, enoent} -> ok; %% Path doesn't exist anyway - {error, Err} -> {error, {Path, Err}} - end; - true -> case prim_file:list_dir(Path) of - {ok, FileNames} -> - case lists:foldl( - fun (FileName, ok) -> - recursive_delete1( - filename:join(Path, FileName)); - (_FileName, Error) -> - Error - end, ok, FileNames) of - ok -> - case prim_file:del_dir(Path) of - ok -> ok; - {error, Err} -> {error, {Path, Err}} - end; - {error, _Err} = Error -> - Error - end; - {error, Err} -> - {error, {Path, Err}} - end - end. - -is_symlink_no_handle(File) -> - case prim_file:read_link(File) of - {ok, _} -> true; - _ -> false - end. - -recursive_copy(Src, Dest) -> - %% Note that this uses the 'file' module and, hence, shouldn't be - %% run on many processes at once. - case is_dir(Src) of - false -> case file:copy(Src, Dest) of - {ok, _Bytes} -> ok; - {error, enoent} -> ok; %% Path doesn't exist anyway - {error, Err} -> {error, {Src, Dest, Err}} - end; - true -> case file:list_dir(Src) of - {ok, FileNames} -> - case file:make_dir(Dest) of - ok -> - lists:foldl( - fun (FileName, ok) -> - recursive_copy( - filename:join(Src, FileName), - filename:join(Dest, FileName)); - (_FileName, Error) -> - Error - end, ok, FileNames); - {error, Err} -> - {error, {Src, Dest, Err}} - end; - {error, Err} -> - {error, {Src, Dest, Err}} - end - end. - -%% TODO: When we stop supporting Erlang prior to R14, this should be -%% replaced with file:open [write, exclusive] -lock_file(Path) -> - case is_file(Path) of - true -> {error, eexist}; - false -> with_handle( - fun () -> {ok, Lock} = prim_file:open(Path, [write]), - ok = prim_file:close(Lock) - end) - end. |