aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/kernel/src/file_io_server.erl64
-rw-r--r--lib/kernel/test/file_SUITE.erl13
2 files changed, 46 insertions, 31 deletions
diff --git a/lib/kernel/src/file_io_server.erl b/lib/kernel/src/file_io_server.erl
index d0ad43afbf..5b2cae6b02 100644
--- a/lib/kernel/src/file_io_server.erl
+++ b/lib/kernel/src/file_io_server.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2013. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2015. 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
@@ -217,23 +217,23 @@ file_request({allocate, Offset, Length},
file_request({pread,At,Sz},
#state{handle=Handle,buf=Buf,read_mode=ReadMode}=State) ->
case position(Handle, At, Buf) of
- {ok,_Offs} ->
+ {error,_} = Reply ->
+ {error,Reply,State};
+ _ ->
case ?PRIM_FILE:read(Handle, Sz) of
{ok,Bin} when ReadMode =:= list ->
std_reply({ok,binary_to_list(Bin)}, State);
Reply ->
std_reply(Reply, State)
- end;
- Reply ->
- std_reply(Reply, State)
+ end
end;
file_request({pwrite,At,Data},
#state{handle=Handle,buf=Buf}=State) ->
case position(Handle, At, Buf) of
- {ok,_Offs} ->
- std_reply(?PRIM_FILE:write(Handle, Data), State);
- Reply ->
- std_reply(Reply, State)
+ {error,_} = Reply ->
+ {error,Reply,State};
+ _ ->
+ std_reply(?PRIM_FILE:write(Handle, Data), State)
end;
file_request(datasync,
#state{handle=Handle}=State) ->
@@ -257,10 +257,10 @@ file_request(close,
file_request({position,At},
#state{handle=Handle,buf=Buf}=State) ->
case position(Handle, At, Buf) of
- {error, _Reason}=Reply ->
- {error,Reply,State};
- Reply ->
- {reply,Reply,State#state{buf= <<>>}}
+ {error,_} = Reply ->
+ {error,Reply,State};
+ Reply ->
+ std_reply(Reply, State)
end;
file_request(truncate,
#state{handle=Handle}=State) ->
@@ -268,13 +268,14 @@ file_request(truncate,
{error,_Reason}=Reply ->
{stop,normal,Reply,State#state{buf= <<>>}};
Reply ->
- {reply,Reply,State}
+ std_reply(Reply, State)
end;
file_request(Unknown,
#state{}=State) ->
Reason = {request, Unknown},
{error,{error,Reason},State}.
+%% Standard reply and clear buffer
std_reply({error,_}=Reply, State) ->
{error,Reply,State#state{buf= <<>>}};
std_reply(Reply, State) ->
@@ -291,7 +292,7 @@ io_request({put_chars, Enc, Chars},
#state{handle=Handle,buf=Buf}=State) ->
case position(Handle, cur, Buf) of
{error,_}=Reply ->
- {stop,normal,Reply,State#state{buf= <<>>}};
+ {stop,normal,Reply,State};
_ ->
put_chars(Chars, Enc, State#state{buf= <<>>})
end;
@@ -372,23 +373,27 @@ io_request_loop([Request|Tail],
%% I/O request put_chars
%%
put_chars(Chars, latin1, #state{handle=Handle, unic=latin1}=State) ->
+ NewState = State#state{buf = <<>>},
case ?PRIM_FILE:write(Handle, Chars) of
{error,_}=Reply ->
- {stop,normal,Reply,State};
+ {stop,normal,Reply,NewState};
Reply ->
- {reply,Reply,State}
+ {reply,Reply,NewState}
end;
put_chars(Chars, InEncoding, #state{handle=Handle, unic=OutEncoding}=State) ->
+ NewState = State#state{buf = <<>>},
case unicode:characters_to_binary(Chars,InEncoding,OutEncoding) of
Bin when is_binary(Bin) ->
case ?PRIM_FILE:write(Handle, Bin) of
{error,_}=Reply ->
- {stop,normal,Reply,State};
+ {stop,normal,Reply,NewState};
Reply ->
- {reply,Reply,State}
+ {reply,Reply,NewState}
end;
{error,_,_} ->
- {stop,normal,{error,{no_translation, InEncoding, OutEncoding}},State}
+ {stop,normal,
+ {error,{no_translation, InEncoding, OutEncoding}},
+ NewState}
end.
%%
@@ -902,11 +907,14 @@ cbv({utf32,little},_) ->
%% Compensates ?PRIM_FILE:position/2 for the number of bytes
%% we have buffered
-
-position(Handle, cur, Buf) ->
- position(Handle, {cur, 0}, Buf);
-position(Handle, {cur, Offs}, Buf) when is_binary(Buf) ->
- ?PRIM_FILE:position(Handle, {cur, Offs-byte_size(Buf)});
-position(Handle, At, _Buf) ->
- ?PRIM_FILE:position(Handle, At).
-
+position(Handle, At, Buf) ->
+ ?PRIM_FILE:position(
+ Handle,
+ case At of
+ cur ->
+ {cur, -byte_size(Buf)};
+ {cur, Offs} ->
+ {cur, Offs-byte_size(Buf)};
+ _ ->
+ At
+ end).
diff --git a/lib/kernel/test/file_SUITE.erl b/lib/kernel/test/file_SUITE.erl
index 2911635db7..e9300bf019 100644
--- a/lib/kernel/test/file_SUITE.erl
+++ b/lib/kernel/test/file_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2013. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2015. 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
@@ -130,7 +130,7 @@ groups() ->
[open1, old_modes, new_modes, path_open, close, access,
read_write, pread_write, append, open_errors,
exclusive]},
- {pos, [], [pos1, pos2]},
+ {pos, [], [pos1, pos2, pos3]},
{file_info, [],
[file_info_basic_file, file_info_basic_directory,
file_info_bad, file_info_times, file_write_file_info]},
@@ -1220,7 +1220,7 @@ pos2(Config) when is_list(Config) ->
ok.
pos3(suite) -> [];
-pos3(doc) -> ["When it does not use raw mode, file:postiion had a bug."];
+pos3(doc) -> ["When it does not use raw mode, file:position had a bug."];
pos3(Config) when is_list(Config) ->
?line Dog = test_server:timetrap(test_server:seconds(5)),
?line RootDir = ?config(data_dir, Config),
@@ -1229,8 +1229,15 @@ pos3(Config) when is_list(Config) ->
?line {ok, Fd} = ?FILE_MODULE:open(Name, [read, binary]),
?line {ok, _} = ?FILE_MODULE:read(Fd, 5),
?line {error, einval} = ?FILE_MODULE:position(Fd, {bof, -1}),
+
%% Here ok had returned =(
?line {error, einval} = ?FILE_MODULE:position(Fd, {cur, -10}),
+ %% That test is actually questionable since file:position/2
+ %% is documented to leave the file position undefined after
+ %% it has returned an error. But on Posix systems the position
+ %% is guaranteed to be unchanged after an error return. On e.g
+ %% Windows there is nothing stated about this in the documentation.
+
?line test_server:timetrap_cancel(Dog),
ok.