aboutsummaryrefslogtreecommitdiffstats
path: root/lib/kernel/src/file.erl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/kernel/src/file.erl')
-rw-r--r--lib/kernel/src/file.erl443
1 files changed, 324 insertions, 119 deletions
diff --git a/lib/kernel/src/file.erl b/lib/kernel/src/file.erl
index a42771dfb6..f1a8aa9f77 100644
--- a/lib/kernel/src/file.erl
+++ b/lib/kernel/src/file.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2011. 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
@@ -36,11 +36,11 @@
%% Specialized
-export([ipread_s32bu_p32bu/3]).
%% Generic file contents.
--export([open/2, close/1,
+-export([open/2, close/1, advise/4,
read/2, write/2,
pread/2, pread/3, pwrite/2, pwrite/3,
read_line/1,
- position/2, truncate/1, sync/1,
+ position/2, truncate/1, datasync/1, sync/1,
copy/2, copy/3]).
%% High level operations
-export([consult/1, path_consult/2]).
@@ -61,6 +61,9 @@
-export([ipread_s32bu_p32bu_int/3]).
+%% Types that can be used from other modules -- alphabetically ordered.
+-export_type([date_time/0, fd/0, file_info/0, filename/0, io_device/0,
+ name/0, posix/0]).
%%% Includes and defines
-include("file.hrl").
@@ -72,22 +75,50 @@
-define(RAM_FILE, ram_file). % Module
%% data types
--type filename() :: string().
+-type filename() :: string() | binary().
-type file_info() :: #file_info{}.
--type io_device() :: pid() | #file_descriptor{}.
--type location() :: integer() | {'bof', integer()} | {'cur', integer()}
- | {'eof', integer()} | 'bof' | 'cur' | 'eof'.
--type mode() :: 'read' | 'write' | 'append' | 'raw' | 'binary' |
- {'delayed_write', non_neg_integer(), non_neg_integer()} |
- 'delayed_write' | {'read_ahead', pos_integer()} |
- 'read_ahead' | 'compressed'.
--type bindings() :: any().
+-type fd() :: #file_descriptor{}.
+-type io_device() :: pid() | fd().
+-type location() :: integer() | {'bof', Offset :: integer()}
+ | {'cur', Offset :: integer()}
+ | {'eof', Offset :: integer()} | 'bof' | 'cur' | 'eof'.
+-type mode() :: 'read' | 'write' | 'append'
+ | 'exclusive' | 'raw' | 'binary'
+ | {'delayed_write',
+ Size :: non_neg_integer(),
+ Delay :: non_neg_integer()}
+ | 'delayed_write' | {'read_ahead', Size :: pos_integer()}
+ | 'read_ahead' | 'compressed'
+ | {'encoding', unicode:encoding()}.
+-type deep_list() :: [char() | atom() | deep_list()].
+-type name() :: string() | atom() | deep_list() | (RawFilename :: binary()).
+-type posix() :: 'eacces' | 'eagain' | 'ebadf' | 'ebusy' | 'edquot'
+ | 'eexist' | 'efault' | 'efbig' | 'eintr' | 'einval'
+ | 'eio' | 'eisdir' | 'eloop' | 'emfile' | 'emlink'
+ | 'enametoolong'
+ | 'enfile' | 'enodev' | 'enoent' | 'enomem' | 'enospc'
+ | 'enotblk' | 'enotdir' | 'enotsup' | 'enxio' | 'eperm'
+ | 'epipe' | 'erofs' | 'espipe' | 'esrch' | 'estale'
+ | 'exdev'.
+-type bindings() :: erl_eval:binding_struct().
+
+-type date() :: {Year :: pos_integer(),
+ Month :: pos_integer(),
+ Day ::pos_integer()}.
+-type time() :: {Hour :: non_neg_integer(),
+ Minute :: non_neg_integer(),
+ Second :: non_neg_integer()}.
+-type date_time() :: {date(), time()}.
+-type posix_file_advise() :: 'normal' | 'sequential' | 'random'
+ | 'no_reuse' | 'will_need' | 'dont_need'.
%%%-----------------------------------------------------------------
%%% General functions
--spec format_error(Reason :: posix() | {integer(), atom(), any()}) ->
- string().
+-spec format_error(Reason) -> Chars when
+ Reason :: posix() | badarg | terminated | system_limit
+ | {Line :: integer(), Mod :: module(), Term :: term()},
+ Chars :: string().
format_error({_Line, ?MODULE, undefined_script}) ->
"no value returned from script";
@@ -108,7 +139,9 @@ format_error(terminated) ->
format_error(ErrorId) ->
erl_posix_msg:message(ErrorId).
--spec pid2name(Pid :: pid()) -> {'ok', filename()} | 'undefined'.
+-spec pid2name(Pid) -> {ok, Filename} | undefined when
+ Filename :: filename(),
+ Pid :: pid().
pid2name(Pid) when is_pid(Pid) ->
case whereis(?FILE_SERVER) of
@@ -127,42 +160,61 @@ pid2name(Pid) when is_pid(Pid) ->
%%% File server functions.
%%% Functions that do not operate on a single open file.
%%% Stateless.
--spec get_cwd() -> {'ok', filename()} | {'error', posix()}.
+-spec get_cwd() -> {ok, Dir} | {error, Reason} when
+ Dir :: filename(),
+ Reason :: posix().
get_cwd() ->
call(get_cwd, []).
--spec get_cwd(Drive :: string()) -> {'ok', filename()} | {'error', posix()}.
+-spec get_cwd(Drive) -> {ok, Dir} | {error, Reason} when
+ Drive :: string(),
+ Dir :: filename(),
+ Reason :: posix() | badarg.
get_cwd(Drive) ->
check_and_call(get_cwd, [file_name(Drive)]).
--spec set_cwd(Dirname :: name()) -> 'ok' | {'error', posix()}.
+-spec set_cwd(Dir) -> ok | {error, Reason} when
+ Dir :: name(),
+ Reason :: posix() | badarg.
set_cwd(Dirname) ->
check_and_call(set_cwd, [file_name(Dirname)]).
--spec delete(Name :: name()) -> 'ok' | {'error', posix()}.
+-spec delete(Filename) -> ok | {error, Reason} when
+ Filename :: name(),
+ Reason :: posix() | badarg.
delete(Name) ->
check_and_call(delete, [file_name(Name)]).
--spec rename(From :: name(), To :: name()) -> 'ok' | {'error', posix()}.
+-spec rename(Source, Destination) -> ok | {error, Reason} when
+ Source :: name(),
+ Destination :: name(),
+ Reason :: posix() | badarg.
rename(From, To) ->
check_and_call(rename, [file_name(From), file_name(To)]).
--spec make_dir(Name :: name()) -> 'ok' | {'error', posix()}.
+-spec make_dir(Dir) -> ok | {error, Reason} when
+ Dir :: name(),
+ Reason :: posix() | badarg.
make_dir(Name) ->
check_and_call(make_dir, [file_name(Name)]).
--spec del_dir(Name :: name()) -> 'ok' | {'error', posix()}.
+-spec del_dir(Dir) -> ok | {error, Reason} when
+ Dir :: name(),
+ Reason :: posix() | badarg.
del_dir(Name) ->
check_and_call(del_dir, [file_name(Name)]).
--spec read_file_info(Name :: name()) -> {'ok', #file_info{}} | {'error', posix()}.
+-spec read_file_info(Filename) -> {ok, FileInfo} | {error, Reason} when
+ Filename :: name(),
+ FileInfo :: file_info(),
+ Reason :: posix() | badarg.
read_file_info(Name) ->
check_and_call(read_file_info, [file_name(Name)]).
@@ -172,54 +224,79 @@ read_file_info(Name) ->
altname(Name) ->
check_and_call(altname, [file_name(Name)]).
--spec read_link_info(Name :: name()) -> {'ok', #file_info{}} | {'error', posix()}.
+-spec read_link_info(Name) -> {ok, FileInfo} | {error, Reason} when
+ Name :: name(),
+ FileInfo :: file_info(),
+ Reason :: posix() | badarg.
read_link_info(Name) ->
check_and_call(read_link_info, [file_name(Name)]).
--spec read_link(Name :: name()) -> {'ok', filename()} | {'error', posix()}.
+-spec read_link(Name) -> {ok, Filename} | {error, Reason} when
+ Name :: name(),
+ Filename :: filename(),
+ Reason :: posix() | badarg.
read_link(Name) ->
check_and_call(read_link, [file_name(Name)]).
--spec write_file_info(Name :: name(), Info :: #file_info{}) ->
- 'ok' | {'error', posix()}.
+-spec write_file_info(Filename, FileInfo) -> ok | {error, Reason} when
+ Filename :: name(),
+ FileInfo :: file_info(),
+ Reason :: posix() | badarg.
write_file_info(Name, Info = #file_info{}) ->
check_and_call(write_file_info, [file_name(Name), Info]).
--spec list_dir(Name :: name()) -> {'ok', [filename()]} | {'error', posix()}.
+-spec list_dir(Dir) -> {ok, Filenames} | {error, Reason} when
+ Dir :: name(),
+ Filenames :: [filename()],
+ Reason :: posix() | badarg.
list_dir(Name) ->
check_and_call(list_dir, [file_name(Name)]).
--spec read_file(Name :: name()) -> {'ok', binary()} | {'error', posix()}.
+-spec read_file(Filename) -> {ok, Binary} | {error, Reason} when
+ Filename :: name(),
+ Binary :: binary(),
+ Reason :: posix() | badarg | terminated | system_limit.
read_file(Name) ->
check_and_call(read_file, [file_name(Name)]).
--spec make_link(Old :: name(), New :: name()) -> 'ok' | {'error', posix()}.
+-spec make_link(Existing, New) -> ok | {error, Reason} when
+ Existing :: name(),
+ New :: name(),
+ Reason :: posix() | badarg.
make_link(Old, New) ->
check_and_call(make_link, [file_name(Old), file_name(New)]).
--spec make_symlink(Old :: name(), New :: name()) -> 'ok' | {'error', posix()}.
+-spec make_symlink(Name1, Name2) -> ok | {error, Reason} when
+ Name1 :: name(),
+ Name2 :: name(),
+ Reason :: posix() | badarg.
make_symlink(Old, New) ->
check_and_call(make_symlink, [file_name(Old), file_name(New)]).
--spec write_file(Name :: name(), Bin :: binary()) -> 'ok' | {'error', posix()}.
+-spec write_file(Filename, Bytes) -> ok | {error, Reason} when
+ Filename :: name(),
+ Bytes :: iodata(),
+ Reason :: posix() | badarg | terminated | system_limit.
write_file(Name, Bin) ->
check_and_call(write_file, [file_name(Name), make_binary(Bin)]).
%% This whole operation should be moved to the file_server and prim_file
%% when it is time to change file server protocol again.
-%% Meanwhile, it is implemented here, slihtly less efficient.
-%%
+%% Meanwhile, it is implemented here, slightly less efficient.
--spec write_file(Name :: name(), Bin :: binary(), Modes :: [mode()]) ->
- 'ok' | {'error', posix()}.
+-spec write_file(Filename, Bytes, Modes) -> ok | {error, Reason} when
+ Filename :: name(),
+ Bytes :: iodata(),
+ Modes :: [mode()],
+ Reason :: posix() | badarg | terminated | system_limit.
write_file(Name, Bin, ModeList) when is_list(ModeList) ->
case make_binary(Bin) of
@@ -273,8 +350,11 @@ raw_write_file_info(Name, #file_info{} = Info) ->
%% Contemporary mode specification - list of options
--spec open(Name :: name(), Modes :: [mode()]) ->
- {'ok', io_device()} | {'error', posix()}.
+-spec open(Filename, Modes) -> {ok, IoDevice} | {error, Reason} when
+ Filename :: name(),
+ Modes :: [mode()],
+ IoDevice :: io_device(),
+ Reason :: posix() | badarg | system_limit.
open(Item, ModeList) when is_list(ModeList) ->
case lists:member(raw, ModeList) of
@@ -327,7 +407,9 @@ open(Item, Mode) ->
%%% The File argument must be either a Pid or a handle
%%% returned from ?PRIM_FILE:open.
--spec close(File :: io_device()) -> 'ok' | {'error', posix()}.
+-spec close(IoDevice) -> ok | {error, Reason} when
+ IoDevice :: io_device(),
+ Reason :: posix() | badarg | terminated.
close(File) when is_pid(File) ->
R = file_request(File, close),
@@ -345,10 +427,28 @@ close(#file_descriptor{module = Module} = Handle) ->
close(_) ->
{error, badarg}.
--spec read(File :: io_device(), Size :: non_neg_integer()) ->
- 'eof' | {'ok', [char()] | binary()} | {'error', posix()}.
+-spec advise(IoDevice, Offset, Length, Advise) -> ok | {error, Reason} when
+ IoDevice :: io_device(),
+ Offset :: integer(),
+ Length :: integer(),
+ Advise :: posix_file_advise(),
+ Reason :: posix() | badarg.
+
+advise(File, Offset, Length, Advise) when is_pid(File) ->
+ R = file_request(File, {advise, Offset, Length, Advise}),
+ wait_file_reply(File, R);
+advise(#file_descriptor{module = Module} = Handle, Offset, Length, Advise) ->
+ Module:advise(Handle, Offset, Length, Advise);
+advise(_, _, _, _) ->
+ {error, badarg}.
+
+-spec read(IoDevice, Number) -> {ok, Data} | eof | {error, Reason} when
+ IoDevice :: io_device() | atom(),
+ Number :: non_neg_integer(),
+ Data :: string() | binary(),
+ Reason :: posix() | badarg | terminated.
-read(File, Sz) when is_pid(File), is_integer(Sz), Sz >= 0 ->
+read(File, Sz) when (is_pid(File) orelse is_atom(File)), is_integer(Sz), Sz >= 0 ->
case io:request(File, {get_chars, '', Sz}) of
Data when is_list(Data); is_binary(Data) ->
{ok, Data};
@@ -361,10 +461,12 @@ read(#file_descriptor{module = Module} = Handle, Sz)
read(_, _) ->
{error, badarg}.
--spec read_line(File :: io_device()) ->
- 'eof' | {'ok', [char()] | binary()} | {'error', posix()}.
+-spec read_line(IoDevice) -> {ok, Data} | eof | {error, Reason} when
+ IoDevice :: io_device() | atom(),
+ Data :: string() | binary(),
+ Reason :: posix() | badarg | terminated.
-read_line(File) when is_pid(File) ->
+read_line(File) when (is_pid(File) orelse is_atom(File)) ->
case io:request(File, {get_line, ''}) of
Data when is_list(Data); is_binary(Data) ->
{ok, Data};
@@ -376,9 +478,12 @@ read_line(#file_descriptor{module = Module} = Handle) ->
read_line(_) ->
{error, badarg}.
--spec pread(File :: io_device(),
- LocationNumbers :: [{location(), non_neg_integer()}]) ->
- {'ok', [string() | binary() | 'eof']} | {'error', posix()}.
+-spec pread(IoDevice, LocNums) -> {ok, DataL} | eof | {error, Reason} when
+ IoDevice :: io_device(),
+ LocNums :: [{Location :: location(), Number :: non_neg_integer()}],
+ DataL :: [Data],
+ Data :: string() | binary() | eof,
+ Reason :: posix() | badarg | terminated.
pread(File, L) when is_pid(File), is_list(L) ->
pread_int(File, L, []);
@@ -401,10 +506,13 @@ pread_int(File, [{At, Sz} | T], R) when is_integer(Sz), Sz >= 0 ->
pread_int(_, _, _) ->
{error, badarg}.
--spec pread(File :: io_device(),
- Location :: location(),
- Size :: non_neg_integer()) ->
- 'eof' | {'ok', string() | binary()} | {'error', posix()}.
+-spec pread(IoDevice, Location, Number) ->
+ {ok, Data} | eof | {error, Reason} when
+ IoDevice :: io_device(),
+ Location :: location(),
+ Number :: non_neg_integer(),
+ Data :: string() | binary(),
+ Reason :: posix() | badarg | terminated.
pread(File, At, Sz) when is_pid(File), is_integer(Sz), Sz >= 0 ->
R = file_request(File, {pread, At, Sz}),
@@ -415,10 +523,12 @@ pread(#file_descriptor{module = Module} = Handle, Offs, Sz)
pread(_, _, _) ->
{error, badarg}.
--spec write(File :: io_device(), Byte :: iodata()) ->
- 'ok' | {'error', posix()}.
+-spec write(IoDevice, Bytes) -> ok | {error, Reason} when
+ IoDevice :: io_device() | atom(),
+ Bytes :: iodata(),
+ Reason :: posix() | badarg | terminated.
-write(File, Bytes) when is_pid(File) ->
+write(File, Bytes) when (is_pid(File) orelse is_atom(File)) ->
case make_binary(Bytes) of
Bin when is_binary(Bin) ->
io:request(File, {put_chars,Bin});
@@ -430,8 +540,11 @@ write(#file_descriptor{module = Module} = Handle, Bytes) ->
write(_, _) ->
{error, badarg}.
--spec pwrite(File :: io_device(), L :: [{location(), iodata()}]) ->
- 'ok' | {'error', {non_neg_integer(), posix()}}.
+-spec pwrite(IoDevice, LocBytes) -> ok | {error, {N, Reason}} when
+ IoDevice :: io_device(),
+ LocBytes :: [{Location :: location(), Bytes :: iodata()}],
+ N :: non_neg_integer(),
+ Reason :: posix() | badarg | terminated.
pwrite(File, L) when is_pid(File), is_list(L) ->
pwrite_int(File, L, 0);
@@ -452,10 +565,11 @@ pwrite_int(File, [{At, Bytes} | T], R) ->
pwrite_int(_, _, _) ->
{error, badarg}.
--spec pwrite(File :: io_device(),
- Location :: location(),
- Bytes :: iodata()) ->
- 'ok' | {'error', posix()}.
+-spec pwrite(IoDevice, Location, Bytes) -> ok | {error, Reason} when
+ IoDevice :: io_device(),
+ Location :: location(),
+ Bytes :: iodata(),
+ Reason :: posix() | badarg | terminated.
pwrite(File, At, Bytes) when is_pid(File) ->
R = file_request(File, {pwrite, At, Bytes}),
@@ -465,7 +579,21 @@ pwrite(#file_descriptor{module = Module} = Handle, Offs, Bytes) ->
pwrite(_, _, _) ->
{error, badarg}.
--spec sync(File :: io_device()) -> 'ok' | {'error', posix()}.
+-spec datasync(IoDevice) -> ok | {error, Reason} when
+ IoDevice :: io_device(),
+ Reason :: posix() | badarg | terminated.
+
+datasync(File) when is_pid(File) ->
+ R = file_request(File, datasync),
+ wait_file_reply(File, R);
+datasync(#file_descriptor{module = Module} = Handle) ->
+ Module:datasync(Handle);
+datasync(_) ->
+ {error, badarg}.
+
+-spec sync(IoDevice) -> ok | {error, Reason} when
+ IoDevice :: io_device(),
+ Reason :: posix() | badarg | terminated.
sync(File) when is_pid(File) ->
R = file_request(File, sync),
@@ -475,8 +603,11 @@ sync(#file_descriptor{module = Module} = Handle) ->
sync(_) ->
{error, badarg}.
--spec position(File :: io_device(), Location :: location()) ->
- {'ok',integer()} | {'error', posix()}.
+-spec position(IoDevice, Location) -> {ok, NewPosition} | {error, Reason} when
+ IoDevice :: io_device(),
+ Location :: location(),
+ NewPosition :: integer(),
+ Reason :: posix() | badarg | terminated.
position(File, At) when is_pid(File) ->
R = file_request(File, {position,At}),
@@ -486,7 +617,9 @@ position(#file_descriptor{module = Module} = Handle, At) ->
position(_, _) ->
{error, badarg}.
--spec truncate(File :: io_device()) -> 'ok' | {'error', posix()}.
+-spec truncate(IoDevice) -> ok | {error, Reason} when
+ IoDevice :: io_device(),
+ Reason :: posix() | badarg | terminated.
truncate(File) when is_pid(File) ->
R = file_request(File, truncate),
@@ -496,17 +629,26 @@ truncate(#file_descriptor{module = Module} = Handle) ->
truncate(_) ->
{error, badarg}.
--spec copy(Source :: io_device() | name() | {name(), [mode()]},
- Destination :: io_device() | name() | {name(), [mode()]}) ->
- {'ok', non_neg_integer()} | {'error', posix()}.
+-spec copy(Source, Destination) -> {ok, BytesCopied} | {error, Reason} when
+ Source :: io_device() | Filename | {Filename, Modes},
+ Destination :: io_device() | Filename | {Filename, Modes},
+ Filename :: name(),
+ Modes :: [mode()],
+ BytesCopied :: non_neg_integer(),
+ Reason :: posix() | badarg | terminated.
copy(Source, Dest) ->
copy_int(Source, Dest, infinity).
--spec copy(Source :: io_device() | name() | {name(), [mode()]},
- Destination :: io_device() | name() | {name(), [mode()]},
- Length :: non_neg_integer() | 'infinity') ->
- {'ok', non_neg_integer()} | {'error', posix()}.
+-spec copy(Source, Destination, ByteCount) ->
+ {ok, BytesCopied} | {error, Reason} when
+ Source :: io_device() | Filename | {Filename, Modes},
+ Destination :: io_device() | Filename | {Filename, Modes},
+ Filename :: name(),
+ Modes :: [mode()],
+ ByteCount :: non_neg_integer() | infinity,
+ BytesCopied :: non_neg_integer(),
+ Reason :: posix() | badarg | terminated.
copy(Source, Dest, Length)
when is_integer(Length), Length >= 0;
@@ -728,8 +870,11 @@ ipread_s32bu_p32bu_2(File,
%%% The following functions, built upon the other interface functions,
%%% provide a higher-lever interface to files.
--spec consult(File :: name()) ->
- {'ok', list()} | {'error', posix() | {integer(), atom(), any()}}.
+-spec consult(Filename) -> {ok, Terms} | {error, Reason} when
+ Filename :: name(),
+ Terms :: [term()],
+ Reason :: posix() | badarg | terminated | system_limit
+ | {Line :: integer(), Mod :: module(), Term :: term()}.
consult(File) ->
case open(File, [read]) of
@@ -741,8 +886,14 @@ consult(File) ->
Error
end.
--spec path_consult(Paths :: [name()], File :: name()) ->
- {'ok', list(), filename()} | {'error', posix() | {integer(), atom(), any()}}.
+-spec path_consult(Path, Filename) -> {ok, Terms, FullName} | {error, Reason} when
+ Path :: [Dir],
+ Dir :: name(),
+ Filename :: name(),
+ Terms :: [term()],
+ FullName :: filename(),
+ Reason :: posix() | badarg | terminated | system_limit
+ | {Line :: integer(), Mod :: module(), Term :: term()}.
path_consult(Path, File) ->
case path_open(Path, File, [read]) of
@@ -759,13 +910,19 @@ path_consult(Path, File) ->
E2
end.
--spec eval(File :: name()) -> 'ok' | {'error', posix()}.
+-spec eval(Filename) -> ok | {error, Reason} when
+ Filename :: name(),
+ Reason :: posix() | badarg | terminated | system_limit
+ | {Line :: integer(), Mod :: module(), Term :: term()}.
eval(File) ->
eval(File, erl_eval:new_bindings()).
--spec eval(File :: name(), Bindings :: bindings()) ->
- 'ok' | {'error', posix()}.
+-spec eval(Filename, Bindings) -> ok | {error, Reason} when
+ Filename :: name(),
+ Bindings :: bindings(),
+ Reason :: posix() | badarg | terminated | system_limit
+ | {Line :: integer(), Mod :: module(), Term :: term()}.
eval(File, Bs) ->
case open(File, [read]) of
@@ -777,14 +934,24 @@ eval(File, Bs) ->
Error
end.
--spec path_eval(Paths :: [name()], File :: name()) ->
- {'ok', filename()} | {'error', posix() | {integer(), atom(), any()}}.
+-spec path_eval(Path, Filename) -> {ok, FullName} | {error, Reason} when
+ Path :: [Dir :: name()],
+ Filename :: name(),
+ FullName :: filename(),
+ Reason :: posix() | badarg | terminated | system_limit
+ | {Line :: integer(), Mod :: module(), Term :: term()}.
path_eval(Path, File) ->
path_eval(Path, File, erl_eval:new_bindings()).
--spec path_eval(Paths :: [name()], File :: name(), Bindings :: bindings()) ->
- {'ok', filename()} | {'error', posix() | {integer(), atom(), any()}}.
+-spec path_eval(Path, Filename, Bindings) ->
+ {ok, FullName} | {error, Reason} when
+ Path :: [Dir :: name()],
+ Filename :: name(),
+ Bindings :: bindings(),
+ FullName :: filename(),
+ Reason :: posix() | badarg | terminated | system_limit
+ | {Line :: integer(), Mod :: module(), Term :: term()}.
path_eval(Path, File, Bs) ->
case path_open(Path, File, [read]) of
@@ -801,14 +968,21 @@ path_eval(Path, File, Bs) ->
E2
end.
--spec script(File :: name()) ->
- {'ok', any()} | {'error', posix() | {integer(), atom(), any()}}.
+-spec script(Filename) -> {ok, Value} | {error, Reason} when
+ Filename :: name(),
+ Value :: term(),
+ Reason :: posix() | badarg | terminated | system_limit
+ | {Line :: integer(), Mod :: module(), Term :: term()}.
script(File) ->
script(File, erl_eval:new_bindings()).
--spec script(File :: name(), Bindings :: bindings()) ->
- {'ok', any()} | {'error', posix() | {integer(), atom(), any()}}.
+-spec script(Filename, Bindings) -> {ok, Value} | {error, Reason} when
+ Filename :: name(),
+ Bindings :: bindings(),
+ Value :: term(),
+ Reason :: posix() | badarg | terminated | system_limit
+ | {Line :: integer(), Mod :: module(), Term :: term()}.
script(File, Bs) ->
case open(File, [read]) of
@@ -820,16 +994,27 @@ script(File, Bs) ->
Error
end.
--spec path_script/2 :: (Paths :: [name()], File :: name()) ->
- {'ok', term(), filename()} | {'error', posix() | {integer(), atom(), _}}.
+-spec path_script(Path, Filename) ->
+ {ok, Value, FullName} | {error, Reason} when
+ Path :: [Dir :: name()],
+ Filename :: name(),
+ Value :: term(),
+ FullName :: filename(),
+ Reason :: posix() | badarg | terminated | system_limit
+ | {Line :: integer(), Mod :: module(), Term :: term()}.
path_script(Path, File) ->
path_script(Path, File, erl_eval:new_bindings()).
--spec path_script(Paths :: [name()],
- File :: name(),
- Bindings :: bindings()) ->
- {'ok', term(), filename()} | {'error', posix() | {integer(), atom(), _}}.
+-spec path_script(Path, Filename, Bindings) ->
+ {ok, Value, FullName} | {error, Reason} when
+ Path :: [Dir :: name()],
+ Filename :: name(),
+ Bindings :: bindings(),
+ Value :: term(),
+ FullName :: filename(),
+ Reason :: posix() | badarg | terminated | system_limit
+ | {Line :: integer(), Mod :: module(), Term :: term()}.
path_script(Path, File, Bs) ->
case path_open(Path, File, [read]) of
@@ -854,8 +1039,14 @@ path_script(Path, File, Bs) ->
%% Searches the Paths for file Filename which can be opened with Mode.
%% The path list is ignored if Filename contains an absolute path.
--spec path_open(Paths :: [name()], Name :: name(), Modes :: [mode()]) ->
- {'ok', io_device(), filename()} | {'error', posix()}.
+-spec path_open(Path, Filename, Modes) ->
+ {ok, IoDevice, FullName} | {error, Reason} when
+ Path :: [Dir :: name()],
+ Filename :: name(),
+ Modes :: [mode()],
+ IoDevice :: io_device(),
+ FullName :: filename(),
+ Reason :: posix() | badarg | system_limit.
path_open(PathList, Name, Mode) ->
case file_name(Name) of
@@ -875,47 +1066,57 @@ path_open(PathList, Name, Mode) ->
end
end.
--spec change_mode(Name :: name(), Mode :: integer()) ->
- 'ok' | {'error', posix()}.
+-spec change_mode(Filename, Mode) -> ok | {error, Reason} when
+ Filename :: name(),
+ Mode :: integer(),
+ Reason :: posix() | badarg.
change_mode(Name, Mode)
when is_integer(Mode) ->
write_file_info(Name, #file_info{mode=Mode}).
--spec change_owner(Name :: name(), OwnerId :: integer()) ->
- 'ok' | {'error', posix()}.
+-spec change_owner(Filename, Uid) -> ok | {error, Reason} when
+ Filename :: name(),
+ Uid :: integer(),
+ Reason :: posix() | badarg.
change_owner(Name, OwnerId)
when is_integer(OwnerId) ->
write_file_info(Name, #file_info{uid=OwnerId}).
--spec change_owner(Name :: name(),
- OwnerId :: integer(),
- GroupId :: integer()) ->
- 'ok' | {'error', posix()}.
+-spec change_owner(Filename, Uid, Gid) -> ok | {error, Reason} when
+ Filename :: name(),
+ Uid :: integer(),
+ Gid :: integer(),
+ Reason :: posix() | badarg.
change_owner(Name, OwnerId, GroupId)
when is_integer(OwnerId), is_integer(GroupId) ->
write_file_info(Name, #file_info{uid=OwnerId, gid=GroupId}).
--spec change_group(Name :: name(), GroupId :: integer()) ->
- 'ok' | {'error', posix()}.
+-spec change_group(Filename, Gid) -> ok | {error, Reason} when
+ Filename :: name(),
+ Gid :: integer(),
+ Reason :: posix() | badarg.
change_group(Name, GroupId)
when is_integer(GroupId) ->
write_file_info(Name, #file_info{gid=GroupId}).
--spec change_time(Name :: name(), Time :: date_time()) ->
- 'ok' | {'error', posix()}.
+-spec change_time(Filename, Mtime) -> ok | {error, Reason} when
+ Filename :: name(),
+ Mtime :: date_time(),
+ Reason :: posix() | badarg.
change_time(Name, Time)
when is_tuple(Time) ->
write_file_info(Name, #file_info{mtime=Time}).
--spec change_time(Name :: name(),
- ATime :: date_time(),
- MTime :: date_time()) ->
- 'ok' | {'error', posix()}.
+-spec change_time(Filename, Atime, Mtime) -> ok | {error, Reason} when
+ Filename :: name(),
+ Atime :: date_time(),
+ Mtime :: date_time(),
+ Reason :: posix() | badarg.
change_time(Name, Atime, Mtime)
when is_tuple(Atime), is_tuple(Mtime) ->
@@ -990,22 +1191,26 @@ path_open_first([], _Name, _Mode, LastError) ->
%% Generates a flat file name from a deep list of atoms and
%% characters (integers).
+file_name(N) when is_binary(N) ->
+ N;
file_name(N) ->
try
- file_name_1(N)
+ file_name_1(N,file:native_name_encoding())
catch Reason ->
{error, Reason}
end.
-file_name_1([C|T]) when is_integer(C), C > 0, C =< 255 ->
- [C|file_name_1(T)];
-file_name_1([H|T]) ->
- file_name_1(H) ++ file_name_1(T);
-file_name_1([]) ->
+file_name_1([C|T],latin1) when is_integer(C), C < 256->
+ [C|file_name_1(T,latin1)];
+file_name_1([C|T],utf8) when is_integer(C) ->
+ [C|file_name_1(T,utf8)];
+file_name_1([H|T],E) ->
+ file_name_1(H,E) ++ file_name_1(T,E);
+file_name_1([],_) ->
[];
-file_name_1(N) when is_atom(N) ->
+file_name_1(N,_) when is_atom(N) ->
atom_to_list(N);
-file_name_1(_) ->
+file_name_1(_,_) ->
throw(badarg).
make_binary(Bin) when is_binary(Bin) ->