%%
%% %CopyrightBegin%
%%
%% Copyright Ericsson AB 2001-2010. 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(ram_file_SUITE).
-export([all/1,
%% init/1, fini/1,
init_per_testcase/2, fin_per_testcase/2]).
-export([open_modes/1, open_old_modes/1, pread_pwrite/1, position/1,
truncate/1, sync/1, get_set_file/1, compress/1, uuencode/1,
large_file_errors/1, large_file_light/1, large_file_heavy/1]).
-include("test_server.hrl").
-include_lib("kernel/include/file.hrl").
-define(FILE_MODULE, file). % Name of module to test
-define(RAM_FILE_MODULE, ram_file). % Name of module to test
%%--------------------------------------------------------------------------
all(suite) ->
[open_modes, open_old_modes, pread_pwrite, position,
truncate, sync, get_set_file, compress, uuencode,
large_file_errors, large_file_light, large_file_heavy].
init_per_testcase(Func, Config) when is_atom(Func), is_list(Config) ->
Time =
case Func of
large_file_heavy ->
?t:minutes(5);
_ ->
?t:seconds(10)
end,
Dog = ?t:timetrap(Time),
%% error_logger:info_msg("~p:~p *****~n", [?MODULE, Func]),
[{watchdog, Dog} | Config].
fin_per_testcase(_Func, Config) ->
%% error_logger:info_msg("~p:~p END *****~n", [?MODULE, Func]),
Dog = ?config(watchdog, Config),
?t:timetrap_cancel(Dog).
%%--------------------------------------------------------------------------
%% Test suites
open_modes(suite) ->
[];
open_modes(doc) ->
["Test that the basic read, write and binary options works for open/2."];
open_modes(Config) when is_list(Config) ->
?line Str1 = "The quick brown fox ",
?line Str2 = "jumps over a lazy dog ",
?line Str = Str1 ++ Str2,
?line Bin1 = list_to_binary(Str1),
?line Bin2 = list_to_binary(Str2),
?line Bin = list_to_binary(Str),
%%
open_read_write(?FILE_MODULE, Str1, [ram, read, write], Str2),
open_read(?FILE_MODULE, Str, [ram]),
open_read_write(?FILE_MODULE, Bin1, [ram, binary, read, write], Bin2),
open_read(?FILE_MODULE, Bin, [ram, binary, read]),
%%
ok.
open_old_modes(suite) ->
[];
open_old_modes(doc) ->
["Test that the old style read, write and binary options ",
"works for open/2."];
open_old_modes(Config) when is_list(Config) ->
?line Str1 = "The quick brown fox ",
?line Str2 = "jumps over a lazy dog ",
?line Str = Str1 ++ Str2,
?line Bin1 = list_to_binary(Str1),
?line Bin2 = list_to_binary(Str2),
?line Bin = list_to_binary(Str),
%%
open_read_write(?RAM_FILE_MODULE, Str1, read_write, Str2),
open_read(?RAM_FILE_MODULE, Str, read),
open_read_write(?RAM_FILE_MODULE, Bin1, {binary, read_write}, Bin2),
open_read(?RAM_FILE_MODULE, Bin, {binary, read}),
%%
ok.
open_read_write(Module, Data1, Options, Data2) ->
?line io:format("~p:open_read_write(~p, ~p, ~p, ~p)~n",
[?MODULE, Module, Data1, Options, Data2]),
%%
?line Size1 = sizeof(Data1),
?line Size2 = sizeof(Data2),
?line Data = append(Data1, Data2),
?line Size = Size1 + Size2,
%%
?line {ok, Fd} = Module:open(Data1, Options),
?line {ok, Data1} = Module:read(Fd, Size1),
?line eof = Module:read(Fd, 1),
?line {ok, Zero} = Module:read(Fd, 0),
?line 0 = sizeof(Zero),
?line ok = Module:write(Fd, Data2),
?line {ok, 0} = Module:position(Fd, bof),
?line {ok, Data} = Module:read(Fd, Size),
?line eof = Module:read(Fd, 1),
?line {ok, Zero} = Module:read(Fd, 0),
?line ok = Module:close(Fd),
%%
?line ok.
open_read(Module, Data, Options) ->
?line io:format("~p:open_read(~p, ~p, ~p)~n",
[?MODULE, Module, Data, Options]),
%%
?line Size = sizeof(Data),
%%
?line {ok, Fd} = Module:open(Data, Options),
?line {ok, Data} = Module:read(Fd, Size),
?line eof = Module:read(Fd, 1),
?line {ok, Zero} = Module:read(Fd, 0),
?line 0 = sizeof(Zero),
?line {error, ebadf} = Module:write(Fd, Data),
?line {ok, 0} = Module:position(Fd, bof),
?line {ok, Data} = Module:read(Fd, Size),
?line eof = Module:read(Fd, 1),
?line {ok, Zero} = Module:read(Fd, 0),
?line ok = Module:close(Fd),
%%
?line ok.
pread_pwrite(suite) ->
[];
pread_pwrite(doc) ->
["Test that pread/2,3 and pwrite/2,3 works."];
pread_pwrite(Config) when is_list(Config) ->
?line Str = "Flygande b�ckaziner s�ka hwila p� mjuqa tuvor x",
?line Bin = list_to_binary(Str),
%%
pread_pwrite_test(?FILE_MODULE, Str, [ram, read, write]),
pread_pwrite_test(?FILE_MODULE, Bin, [ram, binary, read, write]),
pread_pwrite_test(?RAM_FILE_MODULE, Str, [read, write]),
pread_pwrite_test(?RAM_FILE_MODULE, Bin, {binary, read_write}),
%%
ok.
pread_pwrite_test(Module, Data, Options) ->
?line io:format("~p:pread_pwrite_test(~p, ~p, ~p)~n",
[?MODULE, Module, Data, Options]),
%%
?line Size = sizeof(Data),
%%
?line {ok, Fd} = Module:open([], Options),
?line ok = Module:pwrite(Fd, 0, Data),
?line {ok, Data} = Module:pread(Fd, 0, Size+1),
?line eof = Module:pread(Fd, Size+1, 1),
?line {ok, Zero} = Module:pread(Fd, Size+1, 0),
?line 0 = sizeof(Zero),
?line ok = Module:pwrite(Fd, [{0, Data}, {Size+17, Data}]),
?line {ok, [Data,
eof,
Data,
Zero]} = Module:pread(Fd, [{Size+17, Size+1},
{2*Size+17+1, 1},
{0, Size},
{2*Size+17+1, 0}]),
?line ok = Module:close(Fd),
%%
?line ok.
position(suite) ->
[];
position(doc) ->
["Test that position/2 works."];
position(Config) when is_list(Config) ->
?line Str = "Att vara eller icke vara, det �r fr�gan. ",
?line Bin = list_to_binary(Str),
%%
position_test(?FILE_MODULE, Str, [ram, read]),
position_test(?FILE_MODULE, Bin, [ram, binary]),
position_test(?RAM_FILE_MODULE, Str, [read]),
position_test(?RAM_FILE_MODULE, Bin, {binary, read}),
%%
ok.
position_test(Module, Data, Options) ->
?line io:format("~p:position_test(~p, ~p, ~p)~n",
[?MODULE, Module, Data, Options]),
%%
?line Size = sizeof(Data),
?line Size_7 = Size+7,
%%
?line Slice_0_2 = slice(Data, 0, 2),
?line Slice_0_3 = slice(Data, 0, 3),
?line Slice_2_5 = slice(Data, 2, 5),
?line Slice_3_4 = slice(Data, 3, 4),
?line Slice_5 = slice(Data, 5, Size),
%%
?line {ok, Fd} = Module:open(Data, Options),
%%
?line io:format("CUR positions"),
?line {ok, Slice_0_2} = Module:read(Fd, 2),
?line {ok, 2} = Module:position(Fd, cur),
?line {ok, Slice_2_5} = Module:read(Fd, 5),
?line {ok, 3} = Module:position(Fd, {cur, -4}),
?line {ok, Slice_3_4} = Module:read(Fd, 4),
?line {ok, 0} = Module:position(Fd, {cur, -7}),
?line {ok, Slice_0_3} = Module:read(Fd, 3),
?line {ok, 0} = Module:position(Fd, {cur, -3}),
?line {error, einval} = Module:position(Fd, {cur, -1}),
?line {ok, 0} = Module:position(Fd, 0),
?line {ok, 2} = Module:position(Fd, {cur, 2}),
?line {ok, Slice_2_5} = Module:read(Fd, 5),
?line {ok, Size_7} = Module:position(Fd, {cur, Size}),
?line {ok, Zero} = Module:read(Fd, 0),
?line 0 = sizeof(Zero),
?line eof = Module:read(Fd, 1),
%%
?line io:format("Absolute and BOF positions"),
?line {ok, Size} = Module:position(Fd, Size),
?line eof = Module:read(Fd, 1),
?line {ok, 5} = Module:position(Fd, 5),
?line {ok, Slice_5} = Module:read(Fd, Size),
?line {ok, 2} = Module:position(Fd, {bof, 2}),
?line {ok, Slice_2_5} = Module:read(Fd, 5),
?line {ok, 3} = Module:position(Fd, 3),
?line {ok, Slice_3_4} = Module:read(Fd, 4),
?line {ok, 0} = Module:position(Fd, bof),
?line {ok, Slice_0_2} = Module:read(Fd, 2),
?line {ok, Size_7} = Module:position(Fd, {bof, Size_7}),
?line {ok, Zero} = Module:read(Fd, 0),
%%
?line io:format("EOF positions"),
?line {ok, Size} = Module:position(Fd, eof),
?line eof = Module:read(Fd, 1),
?line {ok, 5} = Module:position(Fd, {eof, -Size+5}),
?line {ok, Slice_5} = Module:read(Fd, Size),
?line {ok, 2} = Module:position(Fd, {eof, -Size+2}),
?line {ok, Slice_2_5} = Module:read(Fd, 5),
?line {ok, 3} = Module:position(Fd, {eof, -Size+3}),
?line {ok, Slice_3_4} = Module:read(Fd, 4),
?line {ok, 0} = Module:position(Fd, {eof, -Size}),
?line {ok, Slice_0_2} = Module:read(Fd, 2),
?line {ok, Size_7} = Module:position(Fd, {eof, 7}),
?line {ok, Zero} = Module:read(Fd, 0),
?line eof = Module:read(Fd, 1),
%%
?line ok.
truncate(suite) ->
[];
truncate(doc) ->
["Test that truncate/1 works."];
truncate(Config) when is_list(Config) ->
?line Str = "M�n �dlare att lida och f�rdraga "
++ "ett bittert �des stygn av pilar, ",
?line Bin = list_to_binary(Str),
%%
ok = truncate_test(?FILE_MODULE, Str, [ram, read, write]),
ok = truncate_test(?FILE_MODULE, Bin, [ram, binary, read, write]),
ok = truncate_test(?RAM_FILE_MODULE, Str, read_write),
ok = truncate_test(?RAM_FILE_MODULE, Bin, [binary, read, write]),
%%
{error, eacces} = truncate_test(?FILE_MODULE, Str, [ram]),
{error, eacces} = truncate_test(?FILE_MODULE, Bin, [ram, binary, read]),
{error, eacces} = truncate_test(?RAM_FILE_MODULE, Str, read),
{error, eacces} = truncate_test(?RAM_FILE_MODULE, Bin, {binary, read}),
%%
ok.
truncate_test(Module, Data, Options) ->
?line io:format("~p:truncate_test(~p, ~p, ~p)~n",
[?MODULE, Module, Data, Options]),
%%
?line Size = sizeof(Data),
?line Size1 = Size-2,
?line Data1 = slice(Data, 0, Size1),
%%
?line {ok, Fd} = Module:open(Data, Options),
?line {ok, Size1} = Module:position(Fd, Size1),
?line case Module:truncate(Fd) of
ok ->
?line {ok, 0} = Module:position(Fd, 0),
?line {ok, Data1} = Module:read(Fd, Size),
?line ok = Module:close(Fd),
?line ok;
Error ->
?line ok = Module:close(Fd),
?line Error
end.
sync(suite) ->
[];
sync(doc) ->
["Test that sync/1 at least does not crash."];
sync(Config) when is_list(Config) ->
?line Str = "�n att ta till vapen mot ett hav av kval. ",
?line Bin = list_to_binary(Str),
%%
sync_test(?FILE_MODULE, Str, [ram, read, write]),
sync_test(?FILE_MODULE, Bin, [ram, binary, read, write]),
sync_test(?RAM_FILE_MODULE, Str, read_write),
sync_test(?RAM_FILE_MODULE, Bin, [binary, read, write]),
%%
sync_test(?FILE_MODULE, Str, [ram]),
sync_test(?FILE_MODULE, Bin, [ram, binary, read]),
sync_test(?RAM_FILE_MODULE, Str, read),
sync_test(?RAM_FILE_MODULE, Bin, {binary, read}),
%%
ok.
sync_test(Module, Data, Options) ->
?line io:format("~p:sync_test(~p, ~p, ~p)~n",
[?MODULE, Module, Data, Options]),
%%
?line Size = sizeof(Data),
%%
?line {ok, Fd} = Module:open(Data, Options),
?line ok = Module:sync(Fd),
?line {ok, Data} = Module:read(Fd, Size+1),
?line ok.
get_set_file(suite) ->
[];
get_set_file(doc) ->
["Tests get_file/1, set_file/2, get_file_close/1 and get_size/1."];
get_set_file(Config) when is_list(Config) ->
%% These two strings should not be of equal length.
?line Str = "N�r h�gan nord blir sn�bet�ckt, ",
?line Str2 = "f�r alla harar byta dr�kt. ",
?line Bin = list_to_binary(Str),
?line Bin2 = list_to_binary(Str2),
%%
ok = get_set_file_test(Str, read_write, Str2),
ok = get_set_file_test(Bin, [binary, read, write], Bin2),
ok = get_set_file_test(Str, read, Str2),
ok = get_set_file_test(Bin, [binary, read], Bin2),
%%
ok.
get_set_file_test(Data, Options, Data2) ->
?line io:format("~p:get_set_file_test(~p, ~p, ~p)~n",
[?MODULE, Data, Options, Data2]),
%%
?line Size = sizeof(Data),
?line Size2 = sizeof(Data2),
%%
?line {ok, Fd} = ?RAM_FILE_MODULE:open(Data, Options),
?line {ok, Size} = ?RAM_FILE_MODULE:get_size(Fd),
?line {ok, Data} = ?RAM_FILE_MODULE:get_file(Fd),
?line {ok, Data} = ?RAM_FILE_MODULE:get_file_close(Fd),
?line {error, einval} = ?RAM_FILE_MODULE:get_size(Fd),
?line {ok, Fd2} = ?RAM_FILE_MODULE:open(Data, Options),
?line case ?RAM_FILE_MODULE:set_file(Fd2, Data2) of
{ok, Size2} ->
?line {ok, Size2} = ?RAM_FILE_MODULE:get_size(Fd2),
?line {ok, Data2} = ?RAM_FILE_MODULE:get_file(Fd2),
?line {ok, Data2} = ?RAM_FILE_MODULE:get_file_close(Fd2),
?line ok;
{error, _} = Error ->
?line {ok, Data} = ?RAM_FILE_MODULE:get_file_close(Fd2),
?line Error
end.
compress(suite) ->
[];
compress(doc) ->
["Test that compress/1 and uncompress/1 works."];
compress(Config) when is_list(Config) ->
?line Data = ?config(data_dir, Config),
?line Real = filename:join(Data, "realmen.html"),
?line RealGz = filename:join(Data, "realmen.html.gz"),
%%
%% Uncompress test
%%
?line {ok, FdReal} = ?FILE_MODULE:open(Real, []),
?line {ok, Fd} = ?FILE_MODULE:open([], [ram, read, write]),
?line {ok, FdRealGz} = ?FILE_MODULE:open(RealGz, []),
%%
?line {ok, SzGz} = ?FILE_MODULE:copy(FdRealGz, Fd),
?line {ok, Sz} = ?RAM_FILE_MODULE:uncompress(Fd),
?line {ok, 0} = ?FILE_MODULE:position(Fd, bof),
?line true = compare(FdReal, Fd),
%%
?line true = (SzGz =< Sz),
%%
%% Compress and uncompress test
%%
?line {ok, 0} = ?FILE_MODULE:position(FdReal, bof),
?line {ok, 0} = ?FILE_MODULE:position(Fd, bof),
?line ok = ?FILE_MODULE:truncate(Fd),
?line {ok, Sz} = ?FILE_MODULE:copy(FdReal, Fd),
?line {ok, SzGz} = ?RAM_FILE_MODULE:compress(Fd),
?line {ok, Sz} = ?RAM_FILE_MODULE:uncompress(Fd),
?line {ok, 0} = ?FILE_MODULE:position(Fd, bof),
?line {ok, 0} = ?FILE_MODULE:position(FdReal, bof),
?line true = compare(FdReal, Fd),
%%
?line ok = ?FILE_MODULE:close(FdReal),
?line ok = ?FILE_MODULE:close(Fd),
?line ok = ?FILE_MODULE:close(FdRealGz),
%% Test uncompressing data that will be expanded many times.
?line Huge = iolist_to_binary(mk_42(18)),
?line HugeSize = byte_size(Huge),
?line HugeGz = zlib:gzip(Huge),
?line {ok,HugeFd} = ?FILE_MODULE:open([], [ram,read,write,binary]),
?line ok = ?FILE_MODULE:write(HugeFd, HugeGz),
?line {ok,HugeSize} = ?RAM_FILE_MODULE:uncompress(HugeFd),
?line {ok,0} = ?FILE_MODULE:position(HugeFd, bof),
?line {ok,Huge} = ?FILE_MODULE:read(HugeFd, HugeSize),
%% Uncompressing again should do nothing.
?line {ok,HugeSize} = ?RAM_FILE_MODULE:uncompress(HugeFd),
?line {ok,0} = ?FILE_MODULE:position(HugeFd, bof),
?line {ok,Huge} = ?FILE_MODULE:read(HugeFd, HugeSize),
?line ok = ?FILE_MODULE:close(HugeFd),
ok.
mk_42(0) ->
[42];
mk_42(N) ->
B = mk_42(N-1),
[B|B].
uuencode(suite) ->
[];
uuencode(doc) ->
["Test that uuencode/1 and uudecode/1 works."];
uuencode(Config) when is_list(Config) ->
?line Data = ?config(data_dir, Config),
?line Real = filename:join(Data, "realmen.html"),
?line RealUu = filename:join(Data, "realmen.html.uu"),
%%
%% Uudecode test
%%
?line {ok, FdReal} = ?FILE_MODULE:open(Real, []),
?line {ok, Fd} = ?FILE_MODULE:open([], [ram, read, write]),
?line {ok, FdRealUu} = ?FILE_MODULE:open(RealUu, []),
%%
?line {ok, SzUu} = ?FILE_MODULE:copy(FdRealUu, Fd),
?line {ok, Sz} = ?RAM_FILE_MODULE:uudecode(Fd),
?line true = (Sz =< SzUu),
?line {ok, 0} = ?FILE_MODULE:position(Fd, bof),
?line true = compare(FdReal, Fd),
%%
%% Uuencode and decode test
%%
F = fun(Offs) ->
Size = Sz - Offs,
?line {ok, Offs} = ?FILE_MODULE:position(FdReal, {bof,Offs}),
?line {ok, 0} = ?FILE_MODULE:position(Fd, bof),
?line ok = ?FILE_MODULE:truncate(Fd),
?line {ok, Size} = ?FILE_MODULE:copy(FdReal, Fd),
?line {ok, SizeUu} = ?RAM_FILE_MODULE:uuencode(Fd),
?line true = (Size =< SizeUu),
?line {ok, Size} = ?RAM_FILE_MODULE:uudecode(Fd),
?line {ok, Offs} = ?FILE_MODULE:position(FdReal, {bof,Offs}),
?line {ok, 0} = ?FILE_MODULE:position(Fd, bof),
?line true = compare(FdReal, Fd)
end,
lists:foreach(F, lists:seq(0,Sz-1, 43)),
?line ok = ?FILE_MODULE:close(FdReal),
?line ok = ?FILE_MODULE:close(Fd),
?line ok = ?FILE_MODULE:close(FdRealUu),
%%
ok.
large_file_errors(suite) ->
[];
large_file_errors(doc) ->
["Test error checking of large file offsets."];
large_file_errors(Config) when is_list(Config) ->
?line TwoGig = 1 bsl 31,
?line {ok,Fd} = ?RAM_FILE_MODULE:open("1234567890", [read,write]),
?line {error, einval} = ?FILE_MODULE:read(Fd, TwoGig),
?line {error, badarg} = ?FILE_MODULE:read(Fd, -1),
?line {error, einval} = ?FILE_MODULE:position(Fd, {bof,TwoGig}),
?line {error, einval} = ?FILE_MODULE:position(Fd, {bof,-TwoGig-1}),
?line {error, einval} = ?FILE_MODULE:position(Fd, {bof,-1}),
?line {error, einval} = ?FILE_MODULE:position(Fd, {cur,TwoGig}),
?line {error, einval} = ?FILE_MODULE:position(Fd, {cur,-TwoGig-1}),
?line {error, einval} = ?FILE_MODULE:position(Fd, {eof,TwoGig}),
?line {error, einval} = ?FILE_MODULE:position(Fd, {eof,-TwoGig-1}),
?line {error, einval} = ?FILE_MODULE:pread(Fd, TwoGig, 1),
?line {error, einval} = ?FILE_MODULE:pread(Fd, -TwoGig-1, 1),
?line {error, einval} = ?FILE_MODULE:pread(Fd, -1, 1),
?line {error, einval} = ?FILE_MODULE:pwrite(Fd, TwoGig, "@"),
?line {error, einval} = ?FILE_MODULE:pwrite(Fd, -TwoGig-1, "@"),
?line {error, einval} = ?FILE_MODULE:pwrite(Fd, -1, "@"),
?line {error, einval} = ?FILE_MODULE:pread(Fd, TwoGig, 0),
?line {error, einval} = ?FILE_MODULE:pread(Fd, -TwoGig-1, 0),
?line {error, einval} = ?FILE_MODULE:pread(Fd, -1, 0),
?line ok = ?FILE_MODULE:close(Fd),
ok.
large_file_light(suite) ->
[];
large_file_light(doc) ->
["Test light operations on a \"large\" ram_file."];
large_file_light(Config) when is_list(Config) ->
?line PrivDir = ?config(priv_dir, Config),
%% Marker for next test case that is to heavy to run in a suite.
?line ok = ?FILE_MODULE:write_file(
filename:join(PrivDir, large_file_light),
<<"TAG">>),
%%
?line Data = "abcdefghijklmnopqrstuvwzyz",
?line Size = sizeof(Data),
?line Max = (1 bsl 31) - 1,
?line Max__1 = Max - 1,
?line {ok, Fd} = ?RAM_FILE_MODULE:open(Data, [read]),
?line {ok, Data} = ?FILE_MODULE:read(Fd, Size+1),
?line {ok, Max__1} = ?FILE_MODULE:position(Fd, {eof, Max-Size-1}),
?line eof = ?FILE_MODULE:read(Fd, 1),
?line {ok, Max} = ?FILE_MODULE:position(Fd, {bof, Max}),
?line {ok, Zero} = ?FILE_MODULE:read(Fd, 0),
?line 0 = sizeof(Zero),
?line eof = ?FILE_MODULE:read(Fd, 1),
?line eof = ?FILE_MODULE:pread(Fd, Max__1, 1),
?line {ok, Zero} = ?FILE_MODULE:pread(Fd, Max, 0),
?line eof = ?FILE_MODULE:pread(Fd, Max, 1),
ok.
large_file_heavy(suite) ->
[];
large_file_heavy(doc) ->
["Test operations on a maximum size (2 GByte - 1) ram_file."];
large_file_heavy(Config) when is_list(Config) ->
?line PrivDir = ?config(priv_dir, Config),
%% Check previous test case marker.
case ?FILE_MODULE:read_file_info(
filename:join(PrivDir, large_file_light)) of
{ok,_} ->
{skipped,"Too heavy for casual testing!"};
_ ->
do_large_file_heavy(Config)
end.
do_large_file_heavy(_Config) ->
?line Data = "qwertyuiopasdfghjklzxcvbnm",
?line Size = sizeof(Data),
?line Max = (1 bsl 31) - 1,
?line Max__1 = Max - 1,
?line Max__3 = Max - 3,
?line {ok, Fd} = ?RAM_FILE_MODULE:open(Data, [read,write]),
?line {ok, Data} = ?FILE_MODULE:read(Fd, Size+1),
?line {ok, Max} = ?FILE_MODULE:position(Fd, {eof, Max-Size}),
?line eof = ?FILE_MODULE:read(Fd, 1),
?line erlang:display({allocating,2,'GByte',please,be,patient,'...'}),
?line ok = ?FILE_MODULE:write(Fd, ""),
?line erlang:display({allocating,2,'GByte',succeeded}),
?line {ok, Max__1} = ?FILE_MODULE:position(Fd, {eof, -1}),
?line {ok, [0]} = ?FILE_MODULE:read(Fd, 1),
?line {ok, []} = ?FILE_MODULE:read(Fd, 0),
?line eof = ?FILE_MODULE:read(Fd, 1),
?line ok = ?FILE_MODULE:pwrite(Fd, Max-3, "TAG"),
?line {ok, Max} = ?FILE_MODULE:position(Fd, cur),
?line {ok, Max__3} = ?FILE_MODULE:position(Fd, {eof, -3}),
?line {ok, "TAG"} = ?FILE_MODULE:read(Fd, 3+1),
?line {ok, Max__3} = ?FILE_MODULE:position(Fd, {cur, -3}),
?line ok = ?FILE_MODULE:write(Fd, "tag"),
?line {ok, Max} = ?FILE_MODULE:position(Fd, cur),
?line {ok, 0} = ?FILE_MODULE:position(Fd, bof),
?line {ok, "tag"} = ?FILE_MODULE:pread(Fd, Max__3, 3+1),
?line {ok, 0} = ?FILE_MODULE:position(Fd, cur),
?line ok = ?FILE_MODULE:close(Fd),
ok.
%%--------------------------------------------------------------------------
%% Utility functions
compare(FdA, FdB) ->
Size = 65536,
case {?FILE_MODULE:read(FdA, Size), ?FILE_MODULE:read(FdB, Size)} of
{{error, _} = Error, _} ->
Error;
{_, {error, _} = Error} ->
Error;
{{ok, A}, {ok, B}} ->
case compare_data(A, B) of
true ->
compare(FdA, FdB);
false ->
false
end;
{eof, eof} ->
true;
_ ->
false
end.
compare_data(A, B) when is_list(A), is_list(B) ->
list_to_binary(A) == list_to_binary(B);
compare_data(A, B) when is_list(A), is_binary(B) ->
list_to_binary(A) == B;
compare_data(A, B) when is_binary(A), is_list(B) ->
A == list_to_binary(B);
compare_data(A, B) when is_binary(A), is_binary(B) ->
A == B.
sizeof(Data) when is_list(Data) ->
length(Data);
sizeof(Data) when is_binary(Data) ->
byte_size(Data).
append(Data1, Data2) when is_list(Data1), is_list(Data2) ->
Data1 ++ Data2;
append(Data1, Data2) when is_binary(Data1), is_binary(Data2) ->
list_to_binary([Data1 | Data2]).
slice(Data, Start, Length) when is_list(Data) ->
lists:sublist(Data, Start+1, Length);
slice(Data, Start, Length) when is_binary(Data) ->
{_, Bin} = split_binary(Data, Start),
if
Length >= byte_size(Bin) ->
Bin;
true ->
{B, _} = split_binary(Bin, Length),
B
end.