From e7b0c8c6e72d8b0b60eb00e7e66fea2769963dc2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn-Egil=20Dahlberg?= Date: Mon, 27 Jun 2011 11:17:04 +0200 Subject: Teach file.erl datetime conversions --- lib/kernel/src/file.erl | 73 +++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 68 insertions(+), 5 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/src/file.erl b/lib/kernel/src/file.erl index 0b0f91d86a..bdafcf2cfb 100644 --- a/lib/kernel/src/file.erl +++ b/lib/kernel/src/file.erl @@ -28,9 +28,10 @@ %% File system and metadata. -export([get_cwd/0, get_cwd/1, set_cwd/1, delete/1, rename/2, make_dir/1, del_dir/1, list_dir/1, - read_file_info/1, write_file_info/2, + read_file_info/1, read_file_info/2, + write_file_info/2, write_file_info/3, altname/1, - read_link_info/1, read_link/1, + read_link_info/1, read_link_info/2, read_link/1, make_link/2, make_symlink/2, read_file/1, write_file/2, write_file/3]). %% Specialized @@ -212,7 +213,10 @@ del_dir(Name) -> Reason :: posix() | badarg. read_file_info(Name) -> - check_and_call(read_file_info, [file_name(Name)]). + file_info_time(local, check_and_call(read_file_info, [file_name(Name)])). + +read_file_info(Name, Opts) when is_list(Opts) -> + file_info_time(proplists:get_value(time, Opts, local), check_and_call(read_file_info, [file_name(Name)])). -spec altname(Name :: name()) -> any(). @@ -225,7 +229,10 @@ altname(Name) -> Reason :: posix() | badarg. read_link_info(Name) -> - check_and_call(read_link_info, [file_name(Name)]). + read_link_info(Name, [{time, local}]). + +read_link_info(Name, Opts) when is_list(Opts) -> + file_info_time(proplists:get_value(time, Opts, local), check_and_call(read_link_info, [file_name(Name)])). -spec read_link(Name) -> {ok, Filename} | {error, Reason} when Name :: name(), @@ -241,7 +248,10 @@ read_link(Name) -> Reason :: posix() | badarg. write_file_info(Name, Info = #file_info{}) -> - check_and_call(write_file_info, [file_name(Name), Info]). + check_and_call(write_file_info, [file_name(Name), file_info_epochs(local, Info)]). + +write_file_info(Name, Info = #file_info{}, Opts) when is_list(Opts) -> + check_and_call(write_file_info, [file_name(Name), file_info_epochs(proplists:get_value(time, Opts, local), Info)]). -spec list_dir(Dir) -> {ok, Filenames} | {error, Reason} when Dir :: name(), @@ -1321,6 +1331,59 @@ fname_join(Dir, Name) -> %%%----------------------------------------------------------------- %%% Utility functions. +%% convert file times. +%% all times from prime_file (and file_server) are in unix epochs + +%% from_epochs +file_info_time(epoch, {ok, FI}) -> FI; +file_info_time(local, {ok, #file_info{ atime = Atime, ctime = Ctime, mtime = Mtime } = FI}) -> + {ok, FI#file_info{ + atime = time_epochs_to_local(Atime), + ctime = time_epochs_to_local(Ctime), + mtime = time_epochs_to_local(Mtime) + } + }; +file_info_time(utc, {ok, #file_info{ atime = Atime, ctime = Ctime, mtime = Mtime } = FI}) -> + {ok, FI#file_info{ + atime = time_epochs_to_utc(Atime), + ctime = time_epochs_to_utc(Ctime), + mtime = time_epochs_to_utc(Mtime) + } + }; +file_info_time(_, Error) -> Error. + +%% from_epochs +file_info_epochs(epoch, FI) -> FI; +file_info_epochs(local, #file_info{ atime = Atime, ctime = Ctime, mtime = Mtime } = FI) -> + FI#file_info{ + atime = time_local_to_epochs(Atime), + ctime = time_local_to_epochs(Ctime), + mtime = time_local_to_epochs(Mtime) + }; +file_info_epochs(utc, {ok, #file_info{ atime = Atime, ctime = Ctime, mtime = Mtime } = FI}) -> + FI#file_info{ + atime = time_utc_to_epochs(Atime), + ctime = time_utc_to_epochs(Ctime), + mtime = time_utc_to_epochs(Mtime) + }. + + +-define(DAYS_FROM_0_TO_1970, 719528). +-define(SECONDS_PER_DAY, 86400). + +time_epochs_to_utc(Seconds) when is_integer(Seconds) -> + calendar:gregorian_seconds_to_datetime(Seconds + ?SECONDS_PER_DAY * ?DAYS_FROM_0_TO_1970). + +time_epochs_to_local(Seconds) when is_integer(Seconds) -> + erlang:universaltime_to_localtime(calendar:gregorian_seconds_to_datetime(Seconds + ?SECONDS_PER_DAY * ?DAYS_FROM_0_TO_1970)). + +time_utc_to_epochs({_, _} = Datetime) -> + calendar:datetime_to_gregorian_seconds(Datetime) - ?SECONDS_PER_DAY * ?DAYS_FROM_0_TO_1970. + +time_local_to_epochs({_, _} = Datetime) -> + calendar:datetime_to_gregorian_seconds(erlang:localtime_to_universaltime(Datetime)) - ?SECONDS_PER_DAY * ?DAYS_FROM_0_TO_1970. + + %% file_name(FileName) %% Generates a flat file name from a deep list of atoms and %% characters (integers). -- cgit v1.2.3 From c489db32a796be2d7de7a683544c333a77d917b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn-Egil=20Dahlberg?= Date: Wed, 29 Jun 2011 15:20:38 +0200 Subject: Fix undefined datetimes --- lib/kernel/src/file.erl | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/src/file.erl b/lib/kernel/src/file.erl index bdafcf2cfb..8f027f5a40 100644 --- a/lib/kernel/src/file.erl +++ b/lib/kernel/src/file.erl @@ -1378,10 +1378,15 @@ time_epochs_to_local(Seconds) when is_integer(Seconds) -> erlang:universaltime_to_localtime(calendar:gregorian_seconds_to_datetime(Seconds + ?SECONDS_PER_DAY * ?DAYS_FROM_0_TO_1970)). time_utc_to_epochs({_, _} = Datetime) -> - calendar:datetime_to_gregorian_seconds(Datetime) - ?SECONDS_PER_DAY * ?DAYS_FROM_0_TO_1970. + calendar:datetime_to_gregorian_seconds(Datetime) - ?SECONDS_PER_DAY * ?DAYS_FROM_0_TO_1970; +time_utc_to_epochs(undefined) -> + time_utc_to_epochs(erlang:universaltime()). + time_local_to_epochs({_, _} = Datetime) -> - calendar:datetime_to_gregorian_seconds(erlang:localtime_to_universaltime(Datetime)) - ?SECONDS_PER_DAY * ?DAYS_FROM_0_TO_1970. + calendar:datetime_to_gregorian_seconds(erlang:localtime_to_universaltime(Datetime)) - ?SECONDS_PER_DAY * ?DAYS_FROM_0_TO_1970; +time_local_to_epochs(undefined) -> + time_utc_to_epochs(erlang:universaltime()). %% file_name(FileName) -- cgit v1.2.3 From f21b72789018cf5ac581d851685162194b049d11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn-Egil=20Dahlberg?= Date: Wed, 30 Nov 2011 19:08:38 +0100 Subject: stdlib: Fix return file_info on epoch --- lib/kernel/src/file.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/kernel') diff --git a/lib/kernel/src/file.erl b/lib/kernel/src/file.erl index 8f027f5a40..dafd2c6909 100644 --- a/lib/kernel/src/file.erl +++ b/lib/kernel/src/file.erl @@ -1335,7 +1335,7 @@ fname_join(Dir, Name) -> %% all times from prime_file (and file_server) are in unix epochs %% from_epochs -file_info_time(epoch, {ok, FI}) -> FI; +file_info_time(epoch, {ok, FI} = R) -> R; file_info_time(local, {ok, #file_info{ atime = Atime, ctime = Ctime, mtime = Mtime } = FI}) -> {ok, FI#file_info{ atime = time_epochs_to_local(Atime), -- cgit v1.2.3 From f356bb25df7fe4d6a20d7427b4b4249e9219157c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn-Egil=20Dahlberg?= Date: Fri, 18 Nov 2011 18:02:12 +0100 Subject: Move datetime into prim_file --- lib/kernel/src/file.erl | 135 +++++++++++++++++++++++------------------ lib/kernel/src/file_server.erl | 9 +++ 2 files changed, 84 insertions(+), 60 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/src/file.erl b/lib/kernel/src/file.erl index dafd2c6909..d8ade07336 100644 --- a/lib/kernel/src/file.erl +++ b/lib/kernel/src/file.erl @@ -31,7 +31,8 @@ read_file_info/1, read_file_info/2, write_file_info/2, write_file_info/3, altname/1, - read_link_info/1, read_link_info/2, read_link/1, + read_link_info/1, read_link_info/2, + read_link/1, make_link/2, make_symlink/2, read_file/1, write_file/2, write_file/3]). %% Specialized @@ -213,10 +214,16 @@ del_dir(Name) -> Reason :: posix() | badarg. read_file_info(Name) -> - file_info_time(local, check_and_call(read_file_info, [file_name(Name)])). + check_and_call(read_file_info, [file_name(Name)]). + +-spec read_file_info(Filename, Opts) -> {ok, FileInfo} | {error, Reason} when + Filename :: name(), + Opts :: list(), + FileInfo :: file_info(), + Reason :: posix() | badarg. read_file_info(Name, Opts) when is_list(Opts) -> - file_info_time(proplists:get_value(time, Opts, local), check_and_call(read_file_info, [file_name(Name)])). + check_and_call(read_file_info, [file_name(Name), Opts]). -spec altname(Name :: name()) -> any(). @@ -229,10 +236,11 @@ altname(Name) -> Reason :: posix() | badarg. read_link_info(Name) -> - read_link_info(Name, [{time, local}]). + check_and_call(read_link_info, [file_name(Name)]). read_link_info(Name, Opts) when is_list(Opts) -> - file_info_time(proplists:get_value(time, Opts, local), check_and_call(read_link_info, [file_name(Name)])). + check_and_call(read_link_info, [file_name(Name),Opts]). + -spec read_link(Name) -> {ok, Filename} | {error, Reason} when Name :: name(), @@ -248,10 +256,17 @@ read_link(Name) -> Reason :: posix() | badarg. write_file_info(Name, Info = #file_info{}) -> - check_and_call(write_file_info, [file_name(Name), file_info_epochs(local, Info)]). + check_and_call(write_file_info, [file_name(Name), Info]). + +-spec write_file_info(Filename, FileInfo, Opts) -> ok | {error, Reason} when + Filename :: name(), + Opts :: list(), + FileInfo :: file_info(), + Reason :: posix() | badarg. + write_file_info(Name, Info = #file_info{}, Opts) when is_list(Opts) -> - check_and_call(write_file_info, [file_name(Name), file_info_epochs(proplists:get_value(time, Opts, local), Info)]). + check_and_call(write_file_info, [file_name(Name), Info, Opts]). -spec list_dir(Dir) -> {ok, Filenames} | {error, Reason} when Dir :: name(), @@ -1335,59 +1350,59 @@ fname_join(Dir, Name) -> %% all times from prime_file (and file_server) are in unix epochs %% from_epochs -file_info_time(epoch, {ok, FI} = R) -> R; -file_info_time(local, {ok, #file_info{ atime = Atime, ctime = Ctime, mtime = Mtime } = FI}) -> - {ok, FI#file_info{ - atime = time_epochs_to_local(Atime), - ctime = time_epochs_to_local(Ctime), - mtime = time_epochs_to_local(Mtime) - } - }; -file_info_time(utc, {ok, #file_info{ atime = Atime, ctime = Ctime, mtime = Mtime } = FI}) -> - {ok, FI#file_info{ - atime = time_epochs_to_utc(Atime), - ctime = time_epochs_to_utc(Ctime), - mtime = time_epochs_to_utc(Mtime) - } - }; -file_info_time(_, Error) -> Error. - -%% from_epochs -file_info_epochs(epoch, FI) -> FI; -file_info_epochs(local, #file_info{ atime = Atime, ctime = Ctime, mtime = Mtime } = FI) -> - FI#file_info{ - atime = time_local_to_epochs(Atime), - ctime = time_local_to_epochs(Ctime), - mtime = time_local_to_epochs(Mtime) - }; -file_info_epochs(utc, {ok, #file_info{ atime = Atime, ctime = Ctime, mtime = Mtime } = FI}) -> - FI#file_info{ - atime = time_utc_to_epochs(Atime), - ctime = time_utc_to_epochs(Ctime), - mtime = time_utc_to_epochs(Mtime) - }. - - --define(DAYS_FROM_0_TO_1970, 719528). --define(SECONDS_PER_DAY, 86400). - -time_epochs_to_utc(Seconds) when is_integer(Seconds) -> - calendar:gregorian_seconds_to_datetime(Seconds + ?SECONDS_PER_DAY * ?DAYS_FROM_0_TO_1970). - -time_epochs_to_local(Seconds) when is_integer(Seconds) -> - erlang:universaltime_to_localtime(calendar:gregorian_seconds_to_datetime(Seconds + ?SECONDS_PER_DAY * ?DAYS_FROM_0_TO_1970)). - -time_utc_to_epochs({_, _} = Datetime) -> - calendar:datetime_to_gregorian_seconds(Datetime) - ?SECONDS_PER_DAY * ?DAYS_FROM_0_TO_1970; -time_utc_to_epochs(undefined) -> - time_utc_to_epochs(erlang:universaltime()). - - -time_local_to_epochs({_, _} = Datetime) -> - calendar:datetime_to_gregorian_seconds(erlang:localtime_to_universaltime(Datetime)) - ?SECONDS_PER_DAY * ?DAYS_FROM_0_TO_1970; -time_local_to_epochs(undefined) -> - time_utc_to_epochs(erlang:universaltime()). - +%file_info_time(epoch, {ok, FI} = R) -> R; +%file_info_time(local, {ok, #file_info{ atime = Atime, ctime = Ctime, mtime = Mtime } = FI}) -> +% {ok, FI#file_info{ +% atime = time_epochs_to_local(Atime), +% ctime = time_epochs_to_local(Ctime), +% mtime = time_epochs_to_local(Mtime) +% } +% }; +%file_info_time(utc, {ok, #file_info{ atime = Atime, ctime = Ctime, mtime = Mtime } = FI}) -> +% {ok, FI#file_info{ +% atime = time_epochs_to_utc(Atime), +% ctime = time_epochs_to_utc(Ctime), +% mtime = time_epochs_to_utc(Mtime) +% } +% }; +%file_info_time(_, Error) -> Error. +% +%%% from_epochs +%file_info_epochs(epoch, FI) -> FI; +%file_info_epochs(local, #file_info{ atime = Atime, ctime = Ctime, mtime = Mtime } = FI) -> +% FI#file_info{ +% atime = time_local_to_epochs(Atime), +% ctime = time_local_to_epochs(Ctime), +% mtime = time_local_to_epochs(Mtime) +% }; +%file_info_epochs(utc, {ok, #file_info{ atime = Atime, ctime = Ctime, mtime = Mtime } = FI}) -> +% FI#file_info{ +% atime = time_utc_to_epochs(Atime), +% ctime = time_utc_to_epochs(Ctime), +% mtime = time_utc_to_epochs(Mtime) +% }. +% +% +%-define(DAYS_FROM_0_TO_1970, 719528). +%-define(SECONDS_PER_DAY, 86400). +% +%time_epochs_to_utc(Seconds) when is_integer(Seconds) -> +% calendar:gregorian_seconds_to_datetime(Seconds + ?SECONDS_PER_DAY * ?DAYS_FROM_0_TO_1970). +% +%time_epochs_to_local(Seconds) when is_integer(Seconds) -> +% erlang:universaltime_to_localtime(calendar:gregorian_seconds_to_datetime(Seconds + ?SECONDS_PER_DAY * ?DAYS_FROM_0_TO_1970)). +% +%time_utc_to_epochs({_, _} = Datetime) -> +% calendar:datetime_to_gregorian_seconds(Datetime) - ?SECONDS_PER_DAY * ?DAYS_FROM_0_TO_1970; +%time_utc_to_epochs(undefined) -> +% time_utc_to_epochs(erlang:universaltime()). +% +% +%time_local_to_epochs({_, _} = Datetime) -> +% calendar:datetime_to_gregorian_seconds(erlang:localtime_to_universaltime(Datetime)) - ?SECONDS_PER_DAY * ?DAYS_FROM_0_TO_1970; +%time_local_to_epochs(undefined) -> +% time_utc_to_epochs(erlang:universaltime()). +% %% file_name(FileName) %% Generates a flat file name from a deep list of atoms and diff --git a/lib/kernel/src/file_server.erl b/lib/kernel/src/file_server.erl index 64c61ba3ac..81f9efcf39 100644 --- a/lib/kernel/src/file_server.erl +++ b/lib/kernel/src/file_server.erl @@ -147,15 +147,24 @@ handle_call({get_cwd, Name}, _From, Handle) -> handle_call({read_file_info, Name}, _From, Handle) -> {reply, ?PRIM_FILE:read_file_info(Handle, Name), Handle}; +handle_call({read_file_info, Name, Opts}, _From, Handle) -> + {reply, ?PRIM_FILE:read_file_info(Handle, Name, Opts), Handle}; + handle_call({altname, Name}, _From, Handle) -> {reply, ?PRIM_FILE:altname(Handle, Name), Handle}; handle_call({write_file_info, Name, Info}, _From, Handle) -> {reply, ?PRIM_FILE:write_file_info(Handle, Name, Info), Handle}; +handle_call({write_file_info, Name, Info, Opts}, _From, Handle) -> + {reply, ?PRIM_FILE:write_file_info(Handle, Name, Info, Opts), Handle}; + handle_call({read_link_info, Name}, _From, Handle) -> {reply, ?PRIM_FILE:read_link_info(Handle, Name), Handle}; +handle_call({read_link_info, Name, Opts}, _From, Handle) -> + {reply, ?PRIM_FILE:read_link_info(Handle, Name, Opts), Handle}; + handle_call({read_link, Name}, _From, Handle) -> {reply, ?PRIM_FILE:read_link(Handle, Name), Handle}; -- cgit v1.2.3 From 4ee95bc5c0113da005feeded022876383879d55c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn-Egil=20Dahlberg?= Date: Wed, 30 Nov 2011 18:12:31 +0100 Subject: Add spec for file:read_link_info/2 --- lib/kernel/src/file.erl | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'lib/kernel') diff --git a/lib/kernel/src/file.erl b/lib/kernel/src/file.erl index d8ade07336..80780700ab 100644 --- a/lib/kernel/src/file.erl +++ b/lib/kernel/src/file.erl @@ -238,6 +238,12 @@ altname(Name) -> read_link_info(Name) -> check_and_call(read_link_info, [file_name(Name)]). +-spec read_link_info(Name, Opts) -> {ok, FileInfo} | {error, Reason} when + Name :: name(), + Opts :: list(), + FileInfo :: file_info(), + Reason :: posix() | badarg. + read_link_info(Name, Opts) when is_list(Opts) -> check_and_call(read_link_info, [file_name(Name),Opts]). @@ -264,7 +270,6 @@ write_file_info(Name, Info = #file_info{}) -> FileInfo :: file_info(), Reason :: posix() | badarg. - write_file_info(Name, Info = #file_info{}, Opts) when is_list(Opts) -> check_and_call(write_file_info, [file_name(Name), Info, Opts]). -- cgit v1.2.3 From bd271023fe529f1b591408226743968085a78556 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn-Egil=20Dahlberg?= Date: Fri, 2 Dec 2011 18:54:19 +0100 Subject: Add file_info_opt tests in prim_file_SUITE --- lib/kernel/test/prim_file_SUITE.erl | 106 +++++++++++++++++++++++++++++++++++- 1 file changed, 104 insertions(+), 2 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/test/prim_file_SUITE.erl b/lib/kernel/test/prim_file_SUITE.erl index 00eda6292f..035817a8bc 100644 --- a/lib/kernel/test/prim_file_SUITE.erl +++ b/lib/kernel/test/prim_file_SUITE.erl @@ -32,7 +32,10 @@ file_info_basic_directory_a/1, file_info_basic_directory_b/1, file_info_bad_a/1, file_info_bad_b/1, file_info_times_a/1, file_info_times_b/1, - file_write_file_info_a/1, file_write_file_info_b/1]). + file_write_file_info_a/1, file_write_file_info_b/1, + file_read_file_info_opts/1, file_write_file_info_opts/1, + file_write_read_file_info_opts/1 + ]). -export([rename_a/1, rename_b/1, access/1, truncate/1, datasync/1, sync/1, read_write/1, pread_write/1, append/1, exclusive/1]). @@ -90,7 +93,10 @@ groups() -> file_info_basic_directory_a, file_info_basic_directory_b, file_info_bad_a, file_info_bad_b, file_info_times_a, file_info_times_b, - file_write_file_info_a, file_write_file_info_b]}, + file_write_file_info_a, file_write_file_info_b, + file_read_file_info_opts, file_write_file_info_opts, + file_write_read_file_info_opts + ]}, {errors, [], [e_delete, e_rename, e_make_dir, e_del_dir]}, {compression, [], @@ -1074,6 +1080,102 @@ file_write_file_info(Config, Handle, Suffix) -> ?line test_server:timetrap_cancel(Dog), ok. +%% Test the write_file_info/3 function. + +file_write_file_info_opts(suite) -> []; +file_write_file_info_opts(doc) -> []; +file_write_file_info_opts(Config) when is_list(Config) -> + {ok, Handle} = ?PRIM_FILE:start(), + Dog = test_server:timetrap(test_server:seconds(10)), + RootDir = get_good_directory(Config), + test_server:format("RootDir = ~p", [RootDir]), + + Name = filename:join(RootDir, atom_to_list(?MODULE) ++"_write_file_info_opts"), + ok = ?PRIM_FILE:write_file(Name, "hello_opts"), + + lists:foreach(fun + ({FI, Opts}) -> + ok = ?PRIM_FILE_call(write_file_info, Handle, [Name, FI, Opts]) + end, [ + {#file_info{ mode=8#600, atime = Time, mtime = Time, ctime = Time}, Opts} || + Opts <- [[{time, epoch}]], + Time <- [ 0,1,-1,100,-100,1000,-1000,10000,-10000 ] + ]), + + lists:foreach(fun + ({FI, Opts}) -> + ok = ?PRIM_FILE_call(write_file_info, Handle, [Name, FI, Opts]) + end, [ + {#file_info{ mode=8#400, atime = Time, mtime = Time, ctime = Time}, Opts} || + Opts <- [[{time, utc}],[{time, local}]], + Time <- [ + {{1970,1,1},{0,0,0}}, + {{1970,1,1},{0,0,1}}, + {{1969,12,31},{23,59,59}}, + {{1908,2,3},{23,59,59}}, + {{2012,2,3},{23,59,59}}, + {{2040,2,3},{23,59,59}}, + erlang:localtime() + ]]), + ok = ?PRIM_FILE:stop(Handle), + test_server:timetrap_cancel(Dog), + ok. + +file_read_file_info_opts(suite) -> []; +file_read_file_info_opts(doc) -> []; +file_read_file_info_opts(Config) when is_list(Config) -> + {ok, Handle} = ?PRIM_FILE:start(), + Dog = test_server:timetrap(test_server:seconds(10)), + RootDir = get_good_directory(Config), + test_server:format("RootDir = ~p", [RootDir]), + + Name = filename:join(RootDir, atom_to_list(?MODULE) ++"_read_file_info_opts"), + ok = ?PRIM_FILE:write_file(Name, "hello_opts"), + + lists:foreach(fun + (Opts) -> + {ok,_} = ?PRIM_FILE_call(read_file_info, Handle, [Name, Opts]) + end, [[{time, Type}] || Type <- [local, utc, epoch]]), + ok = ?PRIM_FILE:stop(Handle), + test_server:timetrap_cancel(Dog), + ok. + +%% Test the write and read back *_file_info/3 functions. + +file_write_read_file_info_opts(suite) -> []; +file_write_read_file_info_opts(doc) -> []; +file_write_read_file_info_opts(Config) when is_list(Config) -> + {ok, Handle} = ?PRIM_FILE:start(), + Dog = test_server:timetrap(test_server:seconds(10)), + RootDir = get_good_directory(Config), + test_server:format("RootDir = ~p", [RootDir]), + + Name = filename:join(RootDir, atom_to_list(?MODULE) ++"_read_write_file_info_opts"), + ok = ?PRIM_FILE:write_file(Name, "hello_opts2"), + + ok = file_write_read_file_info_opts(Handle, Name, {{1989, 04, 28}, {19,30,22}}, [{time, local}]), + ok = file_write_read_file_info_opts(Handle, Name, {{1989, 04, 28}, {19,30,22}}, [{time, utc}]), + ok = file_write_read_file_info_opts(Handle, Name, {{1930, 04, 28}, {19,30,22}}, [{time, local}]), + ok = file_write_read_file_info_opts(Handle, Name, {{1930, 04, 28}, {19,30,22}}, [{time, utc}]), + ok = file_write_read_file_info_opts(Handle, Name, 1, [{time, epoch}]), + ok = file_write_read_file_info_opts(Handle, Name, -1, [{time, epoch}]), + ok = file_write_read_file_info_opts(Handle, Name, 300000, [{time, epoch}]), + ok = file_write_read_file_info_opts(Handle, Name, -300000, [{time, epoch}]), + ok = file_write_read_file_info_opts(Handle, Name, 0, [{time, epoch}]), + + ok = ?PRIM_FILE:stop(Handle), + test_server:timetrap_cancel(Dog), + ok. + +file_write_read_file_info_opts(Handle, Name, Mtime, Opts) -> + {ok, FI} = ?PRIM_FILE_call(read_file_info, Handle, [Name, Opts]), + FI2 = FI#file_info{ mtime = Mtime }, + ok = ?PRIM_FILE_call(write_file_info, Handle, [Name, FI2, Opts]), + {ok, FI2} = ?PRIM_FILE_call(read_file_info, Handle, [Name, Opts]), + ok. + + + %% Returns a directory on a file system that has correct file times. get_good_directory(Config) -> -- cgit v1.2.3 From cf50fadc0133a41e8c4a52c3db05a1d0d6186e7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn-Egil=20Dahlberg?= Date: Fri, 2 Dec 2011 19:54:12 +0100 Subject: Teach #file_info spec unix epochs for file times --- lib/kernel/include/file.hrl | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/include/file.hrl b/lib/kernel/include/file.hrl index 3889bce393..ef42987a3d 100644 --- a/lib/kernel/include/file.hrl +++ b/lib/kernel/include/file.hrl @@ -25,10 +25,11 @@ {size :: non_neg_integer(), % Size of file in bytes. type :: 'device' | 'directory' | 'other' | 'regular' | 'symlink', access :: 'read' | 'write' | 'read_write' | 'none', - atime :: file:date_time(), % The local time the file was last read: - % {{Year, Mon, Day}, {Hour, Min, Sec}}. - mtime :: file:date_time(), % The local time the file was last written. - ctime :: file:date_time(), % The interpretation of this time field + atime :: file:date_time() | integer(), % The local time the file was last read: + % {{Year, Mon, Day}, {Hour, Min, Sec}}. + % atime, ctime, mtime may also be unix epochs() + mtime :: file:date_time() | integer(), % The local time the file was last written. + ctime :: file:date_time() | integer(), % The interpretation of this time field % is dependent on operating system. % On Unix it is the last time the file % or the inode was changed. On Windows, -- cgit v1.2.3 From 9158448a508e3e919739dbee0e8e0cad32445941 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn-Egil=20Dahlberg?= Date: Wed, 7 Dec 2011 15:35:43 +0100 Subject: Remove dead code --- lib/kernel/src/file.erl | 58 ------------------------------------------------- 1 file changed, 58 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/src/file.erl b/lib/kernel/src/file.erl index 80780700ab..7a48d34a09 100644 --- a/lib/kernel/src/file.erl +++ b/lib/kernel/src/file.erl @@ -1351,64 +1351,6 @@ fname_join(Dir, Name) -> %%%----------------------------------------------------------------- %%% Utility functions. -%% convert file times. -%% all times from prime_file (and file_server) are in unix epochs - -%% from_epochs -%file_info_time(epoch, {ok, FI} = R) -> R; -%file_info_time(local, {ok, #file_info{ atime = Atime, ctime = Ctime, mtime = Mtime } = FI}) -> -% {ok, FI#file_info{ -% atime = time_epochs_to_local(Atime), -% ctime = time_epochs_to_local(Ctime), -% mtime = time_epochs_to_local(Mtime) -% } -% }; -%file_info_time(utc, {ok, #file_info{ atime = Atime, ctime = Ctime, mtime = Mtime } = FI}) -> -% {ok, FI#file_info{ -% atime = time_epochs_to_utc(Atime), -% ctime = time_epochs_to_utc(Ctime), -% mtime = time_epochs_to_utc(Mtime) -% } -% }; -%file_info_time(_, Error) -> Error. -% -%%% from_epochs -%file_info_epochs(epoch, FI) -> FI; -%file_info_epochs(local, #file_info{ atime = Atime, ctime = Ctime, mtime = Mtime } = FI) -> -% FI#file_info{ -% atime = time_local_to_epochs(Atime), -% ctime = time_local_to_epochs(Ctime), -% mtime = time_local_to_epochs(Mtime) -% }; -%file_info_epochs(utc, {ok, #file_info{ atime = Atime, ctime = Ctime, mtime = Mtime } = FI}) -> -% FI#file_info{ -% atime = time_utc_to_epochs(Atime), -% ctime = time_utc_to_epochs(Ctime), -% mtime = time_utc_to_epochs(Mtime) -% }. -% -% -%-define(DAYS_FROM_0_TO_1970, 719528). -%-define(SECONDS_PER_DAY, 86400). -% -%time_epochs_to_utc(Seconds) when is_integer(Seconds) -> -% calendar:gregorian_seconds_to_datetime(Seconds + ?SECONDS_PER_DAY * ?DAYS_FROM_0_TO_1970). -% -%time_epochs_to_local(Seconds) when is_integer(Seconds) -> -% erlang:universaltime_to_localtime(calendar:gregorian_seconds_to_datetime(Seconds + ?SECONDS_PER_DAY * ?DAYS_FROM_0_TO_1970)). -% -%time_utc_to_epochs({_, _} = Datetime) -> -% calendar:datetime_to_gregorian_seconds(Datetime) - ?SECONDS_PER_DAY * ?DAYS_FROM_0_TO_1970; -%time_utc_to_epochs(undefined) -> -% time_utc_to_epochs(erlang:universaltime()). -% -% -%time_local_to_epochs({_, _} = Datetime) -> -% calendar:datetime_to_gregorian_seconds(erlang:localtime_to_universaltime(Datetime)) - ?SECONDS_PER_DAY * ?DAYS_FROM_0_TO_1970; -%time_local_to_epochs(undefined) -> -% time_utc_to_epochs(erlang:universaltime()). -% - %% file_name(FileName) %% Generates a flat file name from a deep list of atoms and %% characters (integers). -- cgit v1.2.3 From a37f854be3aaee3786d555a28bb4c8d53384a852 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn-Egil=20Dahlberg?= Date: Wed, 7 Dec 2011 15:53:21 +0100 Subject: Change options to prim_file:*_file_info/* * 'utc' changed to 'universal' * 'epoch' changed to 'posix' This change conforms to other naming already in OTP, e.g. erlang:universaltime_to_localtime/1. --- lib/kernel/test/prim_file_SUITE.erl | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/test/prim_file_SUITE.erl b/lib/kernel/test/prim_file_SUITE.erl index 035817a8bc..e6e0974a95 100644 --- a/lib/kernel/test/prim_file_SUITE.erl +++ b/lib/kernel/test/prim_file_SUITE.erl @@ -1098,7 +1098,7 @@ file_write_file_info_opts(Config) when is_list(Config) -> ok = ?PRIM_FILE_call(write_file_info, Handle, [Name, FI, Opts]) end, [ {#file_info{ mode=8#600, atime = Time, mtime = Time, ctime = Time}, Opts} || - Opts <- [[{time, epoch}]], + Opts <- [[{time, posix}]], Time <- [ 0,1,-1,100,-100,1000,-1000,10000,-10000 ] ]), @@ -1107,7 +1107,7 @@ file_write_file_info_opts(Config) when is_list(Config) -> ok = ?PRIM_FILE_call(write_file_info, Handle, [Name, FI, Opts]) end, [ {#file_info{ mode=8#400, atime = Time, mtime = Time, ctime = Time}, Opts} || - Opts <- [[{time, utc}],[{time, local}]], + Opts <- [[{time, universal}],[{time, local}]], Time <- [ {{1970,1,1},{0,0,0}}, {{1970,1,1},{0,0,1}}, @@ -1135,7 +1135,7 @@ file_read_file_info_opts(Config) when is_list(Config) -> lists:foreach(fun (Opts) -> {ok,_} = ?PRIM_FILE_call(read_file_info, Handle, [Name, Opts]) - end, [[{time, Type}] || Type <- [local, utc, epoch]]), + end, [[{time, Type}] || Type <- [local, universal, posix]]), ok = ?PRIM_FILE:stop(Handle), test_server:timetrap_cancel(Dog), ok. @@ -1154,14 +1154,14 @@ file_write_read_file_info_opts(Config) when is_list(Config) -> ok = ?PRIM_FILE:write_file(Name, "hello_opts2"), ok = file_write_read_file_info_opts(Handle, Name, {{1989, 04, 28}, {19,30,22}}, [{time, local}]), - ok = file_write_read_file_info_opts(Handle, Name, {{1989, 04, 28}, {19,30,22}}, [{time, utc}]), + ok = file_write_read_file_info_opts(Handle, Name, {{1989, 04, 28}, {19,30,22}}, [{time, universal}]), ok = file_write_read_file_info_opts(Handle, Name, {{1930, 04, 28}, {19,30,22}}, [{time, local}]), - ok = file_write_read_file_info_opts(Handle, Name, {{1930, 04, 28}, {19,30,22}}, [{time, utc}]), - ok = file_write_read_file_info_opts(Handle, Name, 1, [{time, epoch}]), - ok = file_write_read_file_info_opts(Handle, Name, -1, [{time, epoch}]), - ok = file_write_read_file_info_opts(Handle, Name, 300000, [{time, epoch}]), - ok = file_write_read_file_info_opts(Handle, Name, -300000, [{time, epoch}]), - ok = file_write_read_file_info_opts(Handle, Name, 0, [{time, epoch}]), + ok = file_write_read_file_info_opts(Handle, Name, {{1930, 04, 28}, {19,30,22}}, [{time, universal}]), + ok = file_write_read_file_info_opts(Handle, Name, 1, [{time, posix}]), + ok = file_write_read_file_info_opts(Handle, Name, -1, [{time, posix}]), + ok = file_write_read_file_info_opts(Handle, Name, 300000, [{time, posix}]), + ok = file_write_read_file_info_opts(Handle, Name, -300000, [{time, posix}]), + ok = file_write_read_file_info_opts(Handle, Name, 0, [{time, posix}]), ok = ?PRIM_FILE:stop(Handle), test_server:timetrap_cancel(Dog), -- cgit v1.2.3 From 965db6494f80e4c784aa3bb1cd96dd925ce8b284 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn-Egil=20Dahlberg?= Date: Wed, 7 Dec 2011 23:37:11 +0100 Subject: Document file:*_file_info/2 * file:read_file_info/2 * file:write_file_info/3 Document options and time behavior. --- lib/kernel/doc/src/file.xml | 52 ++++++++++++++++++++++++++++++++++----------- lib/kernel/src/file.erl | 10 ++++++--- 2 files changed, 47 insertions(+), 15 deletions(-) (limited to 'lib/kernel') diff --git a/lib/kernel/doc/src/file.xml b/lib/kernel/doc/src/file.xml index c6a1f25dd9..b2e6962be8 100644 --- a/lib/kernel/doc/src/file.xml +++ b/lib/kernel/doc/src/file.xml @@ -149,6 +149,9 @@ + + + @@ -412,7 +415,7 @@ file_info(Filename) -> {ok, FileInfo} | {error, Reason} Get information about a file (deprecated) -

This function is obsolete. Use read_file_info/1 +

This function is obsolete. Use read_file_info/1,2 instead.

@@ -1188,6 +1191,7 @@ + Get information about a file

Retrieves information about a file. Returns @@ -1199,6 +1203,20 @@ from which the function is called:

-include_lib("kernel/include/file.hrl"). +

The time type returned in atime, mtime and ctime + is dependent on the time type set in Opts :: {time, Type}. + Type local will return local time, universal will + return universal time and posix will return seconds since + or before unix time epoch which is 1970-01-01 00:00 UTC. + Default is {time, local}. +

+ +

+ Since file times is stored in posix time on most OS it is + faster to query file information with the posix option. +

+
+

The record file_info contains the following fields.

size = integer() @@ -1213,15 +1231,15 @@

The current system access to the file.

- atime = date_time() + atime = date_time() | integer() -

The last (local) time the file was read.

+

The last time the file was read.

- mtime = date_time() + mtime = date_time() | integer() -

The last (local) time the file was written.

+

The last time the file was written.

- ctime = date_time() + ctime = date_time() | integer()

The interpretation of this time field depends on the operating system. On Unix, it is the last time @@ -1377,9 +1395,11 @@ + Get information about a link or file -

This function works like read_file_info/1, except that +

This function works like + read_file_info/1,2 except that if Name is a symbolic link, information about the link will be returned in the file_info record and the type field of the record will be set to @@ -1690,6 +1710,7 @@ + Change information about a file

Change file information. Returns ok if successful, @@ -1700,18 +1721,25 @@ from which the function is called:

-include_lib("kernel/include/file.hrl"). +

The time type set in atime, mtime and ctime + is dependent on the time type set in Opts :: {time, Type}. + Type local will interpret the time set as local, universal will + interpret it as universal time and posix must be seconds since + or before unix time epoch which is 1970-01-01 00:00 UTC. + Default is {time, local}. +

The following fields are used from the record, if they are given.

- atime = date_time() + atime = date_time() | integer() -

The last (local) time the file was read.

+

The last time the file was read.

- mtime = date_time() + mtime = date_time() | integer() -

The last (local) time the file was written.

+

The last time the file was written.

- ctime = date_time() + ctime = date_time() | integer()

On Unix, any value give for this field will be ignored (the "ctime" for the file will be set to the current diff --git a/lib/kernel/src/file.erl b/lib/kernel/src/file.erl index 7a48d34a09..b253b3e901 100644 --- a/lib/kernel/src/file.erl +++ b/lib/kernel/src/file.erl @@ -109,6 +109,10 @@ -type posix_file_advise() :: 'normal' | 'sequential' | 'random' | 'no_reuse' | 'will_need' | 'dont_need'. -type sendfile_option() :: {chunk_size, non_neg_integer()}. +-type file_info_option() :: {'time', 'local'} | {'time', 'universal'} + | {'time', 'posix'}. + + %%%----------------------------------------------------------------- %%% General functions @@ -218,7 +222,7 @@ read_file_info(Name) -> -spec read_file_info(Filename, Opts) -> {ok, FileInfo} | {error, Reason} when Filename :: name(), - Opts :: list(), + Opts :: [file_info_option()], FileInfo :: file_info(), Reason :: posix() | badarg. @@ -240,7 +244,7 @@ read_link_info(Name) -> -spec read_link_info(Name, Opts) -> {ok, FileInfo} | {error, Reason} when Name :: name(), - Opts :: list(), + Opts :: [file_info_option()], FileInfo :: file_info(), Reason :: posix() | badarg. @@ -266,7 +270,7 @@ write_file_info(Name, Info = #file_info{}) -> -spec write_file_info(Filename, FileInfo, Opts) -> ok | {error, Reason} when Filename :: name(), - Opts :: list(), + Opts :: [file_info_option()], FileInfo :: file_info(), Reason :: posix() | badarg. -- cgit v1.2.3 From 4091bb7785c488f65f686f2f92de1ef420d7c81b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn-Egil=20Dahlberg?= Date: Thu, 8 Dec 2011 14:51:56 +0100 Subject: Remove time_t specific test in prim_file_SUITE Remove time_t = Sint64 | Uint32 testcase only. The year 2040 does not exist on Sint32. --- lib/kernel/test/prim_file_SUITE.erl | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'lib/kernel') diff --git a/lib/kernel/test/prim_file_SUITE.erl b/lib/kernel/test/prim_file_SUITE.erl index e6e0974a95..ccf26ee034 100644 --- a/lib/kernel/test/prim_file_SUITE.erl +++ b/lib/kernel/test/prim_file_SUITE.erl @@ -1102,6 +1102,8 @@ file_write_file_info_opts(Config) when is_list(Config) -> Time <- [ 0,1,-1,100,-100,1000,-1000,10000,-10000 ] ]), + % REM: determine date range dependent on time_t = Uint32 | Sint32 | Sint64 + % Determine time_t on os:type()? lists:foreach(fun ({FI, Opts}) -> ok = ?PRIM_FILE_call(write_file_info, Handle, [Name, FI, Opts]) @@ -1114,7 +1116,7 @@ file_write_file_info_opts(Config) when is_list(Config) -> {{1969,12,31},{23,59,59}}, {{1908,2,3},{23,59,59}}, {{2012,2,3},{23,59,59}}, - {{2040,2,3},{23,59,59}}, + {{2037,2,3},{23,59,59}}, erlang:localtime() ]]), ok = ?PRIM_FILE:stop(Handle), -- cgit v1.2.3