%% %% %CopyrightBegin% %% %% Copyright Ericsson AB 2017-2021. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 %% %% Unless required by applicable law or agreed to in writing, software %% distributed under the License is distributed on an "AS IS" BASIS, %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %% See the License for the specific language governing permissions and %% limitations under the License. %% %% %CopyrightEnd% %% -module(raw_file_io_compressed). -export([close/1, sync/1, datasync/1, truncate/1, advise/4, allocate/3, position/2, write/2, pwrite/2, pwrite/3, read_line/1, read/2, pread/2, pread/3, read_handle_info/2]). %% OTP internal. -export([ipread_s32bu_p32bu/3, sendfile/8, internal_get_nif_resource/1]). -export([open_layer/3]). -include("file_int.hrl"). open_layer(Filename, Modes, Options) -> IsAppend = lists:member(append, Modes), IsDeflate = lists:member(write, Modes), IsInflate = lists:member(read, Modes), if IsDeflate, IsInflate; IsAppend -> {error, einval}; IsDeflate, not IsInflate -> start_server_module(raw_file_io_deflate, Filename, Modes, Options); IsInflate -> start_server_module(raw_file_io_inflate, Filename, Modes, Options) end. start_server_module(Module, Filename, Modes, Options) -> Secret = make_ref(), case gen_statem:start(Module, {self(), Secret, Options}, []) of {ok, Pid} -> open_next_layer(Pid, Secret, Filename, Modes); Other -> Other end. open_next_layer(Pid, Secret, Filename, Modes) -> case gen_statem:call(Pid, {'$open', Secret, Filename, Modes}, infinity) of ok -> PublicFd = #file_descriptor{ module = raw_file_io_compressed, data = {self(), Pid} }, {ok, PublicFd}; Other -> Other end. close(Fd) -> wrap_call(Fd, [close]). sync(Fd) -> wrap_call(Fd, [sync]). datasync(Fd) -> wrap_call(Fd, [datasync]). truncate(Fd) -> wrap_call(Fd, [truncate]). advise(Fd, Offset, Length, Advise) -> wrap_call(Fd, [advise, Offset, Length, Advise]). allocate(Fd, Offset, Length) -> wrap_call(Fd, [allocate, Offset, Length]). position(Fd, Mark) -> wrap_call(Fd, [position, Mark]). write(Fd, IOData) -> try CompactedData = erlang:iolist_to_iovec(IOData), wrap_call(Fd, [write, CompactedData]) catch error:badarg -> {error, badarg} end. pwrite(Fd, Offset, IOData) -> try CompactedData = erlang:iolist_to_iovec(IOData), wrap_call(Fd, [pwrite, Offset, CompactedData]) catch error:badarg -> {error, badarg} end. pwrite(Fd, LocBytes) -> try CompactedLocBytes = [ {Offset, erlang:iolist_to_iovec(IOData)} || {Offset, IOData} <- LocBytes ], wrap_call(Fd, [pwrite, CompactedLocBytes]) catch error:badarg -> {error, badarg} end. read_line(Fd) -> wrap_call(Fd, [read_line]). read(Fd, Size) -> wrap_call(Fd, [read, Size]). pread(Fd, Offset, Size) -> wrap_call(Fd, [pread, Offset, Size]). pread(Fd, LocNums) -> wrap_call(Fd, [pread, LocNums]). ipread_s32bu_p32bu(Fd, Offset, MaxSize) -> wrap_call(Fd, [ipread_s32bu_p32bu, Offset, MaxSize]). sendfile(_,_,_,_,_,_,_,_) -> {error, enotsup}. internal_get_nif_resource(_) -> {error, enotsup}. read_handle_info(Fd, Opts) -> wrap_call(Fd, [Opts]). wrap_call(Fd, Command) -> {_Owner, Pid} = get_fd_data(Fd), try gen_statem:call(Pid, Command, infinity) of Result -> Result catch exit:{normal, _StackTrace} -> {error, einval}; exit:{noproc, _StackTrace} -> {error, einval} end. get_fd_data(#file_descriptor{ data = Data }) -> {Owner, _ServerPid} = Data, case self() of Owner -> Data; _ -> error(not_on_controlling_process) end.