From 42a916716671d6f553f5c25d8a8c98d34a7f1da5 Mon Sep 17 00:00:00 2001 From: Hans Nilsson Date: Thu, 27 Jun 2019 16:29:19 +0200 Subject: ssh: The ssh_sftp documentation is now generated --- lib/ssh/doc/src/ssh_sftp.xml | 436 +++++++++++++++--------------------------- lib/ssh/doc/src/using_ssh.xml | 14 +- lib/ssh/src/ssh_sftp.erl | 326 ++++++++++++++++++++++++++++++- 3 files changed, 485 insertions(+), 291 deletions(-) diff --git a/lib/ssh/doc/src/ssh_sftp.xml b/lib/ssh/doc/src/ssh_sftp.xml index c89092798d..76d2b21946 100644 --- a/lib/ssh/doc/src/ssh_sftp.xml +++ b/lib/ssh/doc/src/ssh_sftp.xml @@ -37,60 +37,106 @@ SSH.

-
- DATA TYPES -

Type definitions that are used more than once in this module, - or abstractions to indicate the intended use of the data type, or both: -

- - - reason() - -

= atom() | string() | tuple() A description of the reason why an operation failed.

-

- The atom() value is formed from the sftp error codes in the protocol-level responses as defined in - draft-ietf-secsh-filexfer-13.txt - section 9.1. -

-

+ + Error cause + + + +

A description of the reason why an operation failed.

+

The atom() value is formed from the sftp error codes in the protocol-level responses as defined in + draft-ietf-secsh-filexfer-13 + section 9.1. The codes are named as SSH_FX_* which are transformed into lowercase of the star-part. E.g. the error code SSH_FX_NO_SUCH_FILE will cause the reason() to be no_such_file.

The string() reason is the error information from the server in case of an exit-signal. If that information is empty, the reason is the exit signal name.

-

The tuple() reason are other errors like the {exit_status,integer()} if the exit status is not 0. +

The tuple() reason are other errors like for example {exit_status,1}. +

+ + + + Crypto operations for open_tar + + + + + +

Specifies the encryption or decryption applied to tar files when using + open_tar/3 or + open_tar/4. +

+

The encryption or decryption is applied to the generated stream of + bytes prior to sending the resulting stream to the SFTP server. +

+

For code examples see Section + Example with encryption + in the ssh Users Guide.

-
+ + - connection_ref() = -

opaque() - as returned by - ssh:connect/3

+ + + + + +

The init_fun() in the + tar_crypto_spec + is applied once prior to any other crypto + operation. The intention is that this function initiates the encryption or + decryption for example by calling + crypto:crypto_init/4 + or similar. The crypto_state() is the state such a function may return. +

+

If the selected cipher needs to have the input data partioned into + blocks of a certain size, the init_fun() should return the second + form of return value with the chunk_size() set to the block size. + If the chunk_size() is undefined, the size of the PlainBins varies, + because this is intended for stream crypto, whereas a fixed chunk_size() is intended for block crypto. + A chunk_size() can be changed in the return from the crypto_fun(). + The value can be changed between pos_integer() and undefined. +

+
+
- timeout() -

= infinity | integer() in milliseconds. Default infinity.

-
-
+ + + + +

The initial crypto_state() returned from the + init_fun() + is folded into repeated applications of the crypto_fun() in the + tar_crypto_spec. + The binary returned from that fun is sent to the remote SFTP server and + the new crypto_state() is used in the next call of the + crypto_fun(). +

+

If the crypto_fun() reurns a chunk_size(), that value + is as block size for further blocks in calls to crypto_fun(). +

+
+
-
- Time-outs -

If the request functions for the SFTP channel return {error, timeout}, - no answer was received from the server within the expected time.

-

The request may have reached the server and may have been performed. - However, no answer was received from the server within the expected time.

-
+ + + +

If doing encryption, + the final_fun() in the + tar_crypto_spec + is applied to the last piece of data. + The final_fun() is responsible for padding (if needed) and + encryption of that last piece. +

+
+
+ - apread(ChannelPid, Handle, Position, Len) -> {async, N} | {error, reason()} + Reads asynchronously from an open file. - - ChannelPid = pid() - Handle = term() - Position = integer() - Len = integer() - N = term() -

The function reads from a specified position, combining the position/3 and aread/3 functions.

@@ -98,17 +144,8 @@
- apwrite(ChannelPid, Handle, Position, Data) -> {async, N} | {error, reason()} + Writes asynchronously to an open file. - - ChannelPid = pid() - Handle = term() - Position = integer() - Len = integer() - Data = binary() - Timeout = timeout() - N = term() -

The function writes to a specified position, combining the position/3 and awrite/3 functions.

@@ -116,15 +153,8 @@
- aread(ChannelPid, Handle, Len) -> {async, N} | {error, reason()} + Reads asynchronously from an open file. - - ChannelPid = pid() - Handle = term() - Position = integer() - Len = integer() - N = term() -

Reads from an open file, without waiting for the result. If the handle is valid, the function returns , where N @@ -137,16 +167,8 @@ - awrite(ChannelPid, Handle, Data) -> {async, N} | {error, reason()} + Writes asynchronously to an open file. - - ChannelPid = pid() - Handle = term() - Position = integer() - Len = integer() - Data = binary() - Timeout = timeout() -

Writes to an open file, without waiting for the result. If the handle is valid, the function returns , where N @@ -159,28 +181,18 @@ - close(ChannelPid, Handle) -> - close(ChannelPid, Handle, Timeout) -> ok | {error, reason()} + + Closes an open handle. - - ChannelPid = pid() - Handle = term() - Timeout = timeout() -

Closes a handle to an open file or directory on the server.

- delete(ChannelPid, Name) -> - delete(ChannelPid, Name, Timeout) -> ok | {error, reason()} + + Deletes a file. - - ChannelPid = pid() - Name = string() - Timeout = timeout() -

Deletes the file specified by .

@@ -188,14 +200,9 @@
- del_dir(ChannelPid, Name) -> - del_dir(ChannelPid, Name, Timeout) -> ok | {error, reason()} + + Deletes an empty directory. - - ChannelPid = pid() - Name = string() - Timeout = timeout() -

Deletes a directory specified by . The directory must be empty before it can be successfully deleted. @@ -204,16 +211,9 @@ - list_dir(ChannelPid, Path) -> - list_dir(ChannelPid, Path, Timeout) -> {ok, Filenames} | {error, reason()} + + Lists the directory. - - ChannelPid = pid() - Path = string() - Filenames = [Filename] - Filename = string() - Timeout = timeout() -

Lists the given directory on the server, returning the filenames as a list of strings.

@@ -221,14 +221,9 @@
- make_dir(ChannelPid, Name) -> - make_dir(ChannelPid, Name, Timeout) -> ok | {error, reason()} + + Creates a directory. - - ChannelPid = pid() - Name = string() - Timeout = timeout() -

Creates a directory specified by . must be a full path to a new directory. The directory can only be @@ -237,14 +232,9 @@ - make_symlink(ChannelPid, Name, Target) -> - make_symlink(ChannelPid, Name, Target, Timeout) -> ok | {error, reason()} + + Creates a symbolic link. - - ChannelPid = pid() - Name = string() - Target = string() -

Creates a symbolic link pointing to with the name . @@ -252,32 +242,19 @@ - - open(ChannelPid, File, Mode) -> - open(ChannelPid, File, Mode, Timeout) -> {ok, Handle} | {error, reason()} + + + Opens a file and returns a handle. - - ChannelPid = pid() - File = string() - Mode = [Modeflag] - Modeflag = read | write | creat | trunc | append | binary - Timeout = timeout() - Handle = term() -

Opens a file on the server and returns a handle, which can be used for reading or writing.

- opendir(ChannelPid, Path) -> - opendir(ChannelPid, Path, Timeout) -> {ok, Handle} | {error, reason()} + + Opens a directory and returns a handle. - - ChannelPid = pid() - Path = string() - Timeout = timeout() -

Opens a handle to a directory on the server. The handle can be used for reading directory contents.

@@ -285,72 +262,36 @@
- open_tar(ChannelPid, Path, Mode) -> - open_tar(ChannelPid, Path, Mode, Timeout) -> {ok, Handle} | {error, reason()} + + Opens a tar file on the server to which ChannelPid is connected and returns a handle. - - ChannelPid = pid() - Path = string() - Mode = [read] | [write] | [read,EncryptOpt] | [write,DecryptOpt] - EncryptOpt = {crypto,{InitFun,EncryptFun,CloseFun}} - DecryptOpt = {crypto,{InitFun,DecryptFun}} - InitFun = (fun() -> {ok,CryptoState}) | (fun() -> {ok,CryptoState,ChunkSize}) - CryptoState = any() - ChunkSize = undefined | pos_integer() - EncryptFun = (fun(PlainBin,CryptoState) -> EncryptResult) - EncryptResult = {ok,EncryptedBin,CryptoState} | {ok,EncryptedBin,CryptoState,ChunkSize} - PlainBin = binary() - EncryptedBin = binary() - DecryptFun = (fun(EncryptedBin,CryptoState) -> DecryptResult) - DecryptResult = {ok,PlainBin,CryptoState} | {ok,PlainBin,CryptoState,ChunkSize} - CloseFun = (fun(PlainBin,CryptoState) -> {ok,EncryptedBin}) - Timeout = timeout() -

Opens a handle to a tar file on the server, associated with ChannelPid. - The handle can be used for remote tar creation and extraction, as defined by the - erl_tar:init/3 function. -

- -

For code exampel see Section - SFTP Client with TAR Compression and Encryption in - the ssh Users Guide.

- -

The crypto mode option is applied to the generated stream of bytes prior to sending - them to the SFTP server. This is intended for encryption but can be used for other - purposes. + The handle can be used for remote tar creation and extraction. The actual writing + and reading is performed by calls to + erl_tar:add/3,4 and + erl_tar:extract/2. + Note: The + erl_tar:init/3 function should not + be called, that one is called by this open_tar function.

-

The InitFun is applied once - prior to any other crypto operation. The returned CryptoState is then folded into - repeated applications of the EncryptFun or DecryptFun. The binary returned - from those funs are sent further to the remote SFTP server. Finally, if doing encryption, - the CloseFun is applied to the last piece of data. The CloseFun is - responsible for padding (if needed) and encryption of that last piece. +

For code examples see Section + SFTP Client with TAR Compression + in the ssh Users Guide.

-

The ChunkSize defines the size of the PlainBins that EncodeFun is applied - to. If the ChunkSize is undefined, the size of the PlainBins varies, - because this is intended for stream crypto, whereas a fixed ChunkSize is intended for block crypto. - ChunkSizes can be changed in the return from the EncryptFun or - DecryptFun. The value can be changed between pos_integer() and undefined. +

The crypto mode option is explained in the data types section above, see + Crypto operations for open_tar. + Encryption is assumed if the Mode contains write, and + decryption if the Mode contains read.

-
- position(ChannelPid, Handle, Location) -> - position(ChannelPid, Handle, Location, Timeout) -> {ok, NewPosition | {error, reason()} + + Sets the file position of a file. - - ChannelPid = pid() - Handle = term() - Location = Offset - | {bof, Offset} | {cur, Offset} | {eof, Offset} | bof | cur | eof - Offset = integer() - Timeout = timeout() - NewPosition = integer() -

Sets the file position of the file referenced by . Returns (as an absolute offset) if @@ -384,17 +325,9 @@ - pread(ChannelPid, Handle, Position, Len) -> - pread(ChannelPid, Handle, Position, Len, Timeout) -> {ok, Data} | eof | {error, reason()} + + Reads from an open file. - - ChannelPid = pid() - Handle = term() - Position = integer() - Len = integer() - Timeout = timeout() - Data = string() | binary() -

The function reads from a specified position, combining the position/3 and read/3,4 functions.

@@ -402,16 +335,9 @@
- pwrite(ChannelPid, Handle, Position, Data) -> ok - pwrite(ChannelPid, Handle, Position, Data, Timeout) -> ok | {error, reason()} + + Writes to an open file. - - ChannelPid = pid() - Handle = term() - Position = integer() - Data = iolist() - Timeout = timeout() -

The function writes to a specified position, combining the position/3 and write/3,4 functions.

@@ -419,16 +345,9 @@
- read(ChannelPid, Handle, Len) -> - read(ChannelPid, Handle, Len, Timeout) -> {ok, Data} | eof | {error, reason()} + + Reads from an open file. - - ChannelPid = pid() - Handle = term() - Len = integer() - Timeout = timeout() - Data = string() | binary() -

Reads bytes from the file referenced by . Returns , , or @@ -440,32 +359,19 @@ - - read_file(ChannelPid, File) -> - read_file(ChannelPid, File, Timeout) -> {ok, Data} | {error, reason()} + + + Reads a file. - - ChannelPid = pid() - File = string() - Data = binary() - Timeout = timeout() -

Reads a file from the server, and returns the data in a binary.

- - read_file_info(ChannelPid, Name) -> - read_file_info(ChannelPid, Name, Timeout) -> {ok, FileInfo} | {error, reason()} + + + Gets information about a file. - - ChannelPid = pid() - Name = string() - Handle = term() - Timeout = timeout() - FileInfo = record() -

Returns a record from the file system object specified by or . See @@ -474,38 +380,26 @@

Depending on the underlying OS:es links might be followed and info on the final file, directory - etc is returned. See ssh_sftp::read_link_info/2 + etc is returned. See read_link_info/2 on how to get information on links instead.

- read_link(ChannelPid, Name) -> - read_link(ChannelPid, Name, Timeout) -> {ok, Target} | {error, reason()} + + Reads symbolic link. - - ChannelPid = pid() - Name = string() - Target = string() -

Reads the link target from the symbolic link specified by .

- - read_link_info(ChannelPid, Name) -> {ok, FileInfo} | {error, reason()} - read_link_info(ChannelPid, Name, Timeout) -> {ok, FileInfo} | {error, reason()} + + + Gets information about a symbolic link. - - ChannelPid = pid() - Name = string() - Handle = term() - Timeout = timeout() - FileInfo = record() -

Returns a record from the symbolic link specified by or . @@ -517,15 +411,9 @@ - rename(ChannelPid, OldName, NewName) -> - rename(ChannelPid, OldName, NewName, Timeout) -> ok | {error, reason()} + + Renames a file. - - ChannelPid = pid() - OldName = string() - NewName = string() - Timeout = timeout() -

Renames a file named and gives it the name . @@ -594,11 +482,8 @@ - stop_channel(ChannelPid) -> ok + Stops the SFTP client channel. - - ChannelPid = pid() -

Stops an SFTP channel. Does not close the SSH connection. Use ssh:close/1 to close it.

@@ -606,16 +491,9 @@
- write(ChannelPid, Handle, Data) -> - write(ChannelPid, Handle, Data, Timeout) -> ok | {error, reason()} + + Writes to an open file. - - ChannelPid = pid() - Handle = term() - Position = integer() - Data = iolist() - Timeout = timeout() -

Writes to the file referenced by . The file is to be opened with or @@ -625,15 +503,9 @@ - write_file(ChannelPid, File, Iolist) -> - write_file(ChannelPid, File, Iolist, Timeout) -> ok | {error, reason()} + + Writes a file. - - ChannelPid = pid() - File = string() - Iolist = iolist() - Timeout = timeout() -

Writes a file to the server. The file is created if it does not exist but overwritten if it exists.

@@ -641,15 +513,9 @@
- write_file_info(ChannelPid, Name, Info) -> - write_file_info(ChannelPid, Name, Info, Timeout) -> ok | {error, reason()} + + Writes information for a file. - - ChannelPid = pid() - Name = string() - Info = record() - Timeout = timeout() -

Writes file information from a record to the file specified by . See diff --git a/lib/ssh/doc/src/using_ssh.xml b/lib/ssh/doc/src/using_ssh.xml index 4455d5ecc5..5c56dee81d 100644 --- a/lib/ssh/doc/src/using_ssh.xml +++ b/lib/ssh/doc/src/using_ssh.xml @@ -232,9 +232,10 @@

- SFTP Client with TAR Compression and Encryption - -

Example of writing and then reading a tar file follows:

+ SFTP Client with TAR Compression +
+ Basic example +

This is an example of writing and then reading a tar file:

{ok,HandleWrite} = ssh_sftp:open_tar(ChannelPid, ?tar_file_name, [write]), ok = erl_tar:add(HandleWrite, .... ), @@ -248,8 +249,12 @@ {ok,NameValueList} = erl_tar:extract(HandleRead,[memory]), ok = erl_tar:close(HandleRead), +
-

The previous write and read example can be extended with encryption and decryption as follows:

+
+ Example with encryption +

The previous Basic example + can be extended with encryption and decryption as follows:

%% First three parameters depending on which crypto type we select: Key = <<"This is a 256 bit key. abcdefghi">>, @@ -297,6 +302,7 @@ Cr = {InitFun,DecryptFun}, ok = erl_tar:close(HandleRead),
+
diff --git a/lib/ssh/src/ssh_sftp.erl b/lib/ssh/src/ssh_sftp.erl index 1b2ba5a50b..9162de3487 100644 --- a/lib/ssh/src/ssh_sftp.erl +++ b/lib/ssh/src/ssh_sftp.erl @@ -92,16 +92,26 @@ -define(XF(S), S#state.xf). -define(REQID(S), S#state.req_id). + +-type reason() :: atom() | string() | tuple() . + %%==================================================================== %% API %%==================================================================== start_channel(Cm) when is_pid(Cm) -> start_channel(Cm, []); + start_channel(Socket) when is_port(Socket) -> start_channel(Socket, []); + start_channel(Host) when is_list(Host) -> start_channel(Host, []). + +-spec start_channel(ssh:connection_ref() | gen_tcp:socket() | string(), + ssh:client_options() + ) -> {ok,pid()} | {ok,pid(),ssh:connection_ref()} | {error,term()}. + start_channel(Socket, UserOptions) when is_port(Socket) -> {SshOpts, _ChanOpts, SftpOpts} = handle_options(UserOptions), Timeout = % A mixture of ssh:connect and ssh_sftp:start_channel: @@ -144,6 +154,10 @@ start_channel(Cm, UserOptions) when is_pid(Cm) -> start_channel(Host, UserOptions) -> start_channel(Host, 22, UserOptions). + +-spec start_channel(string(), integer(), ssh:client_options()) -> + {ok,pid(),ssh:connection_ref()} | {error,term()}. + start_channel(Host, Port, UserOptions) -> {SshOpts, ChanOpts, SftpOpts} = handle_options(UserOptions), Timeout = % A mixture of ssh:connect and ssh_sftp:start_channel: @@ -168,6 +182,10 @@ start_channel(Host, Port, UserOptions) -> Error end. + +-spec stop_channel(ChannelPid) -> ok when + ChannelPid :: pid(). + stop_channel(Pid) -> case is_process_alive(Pid) of true -> @@ -188,17 +206,62 @@ stop_channel(Pid) -> wait_for_version_negotiation(Pid, Timeout) -> call(Pid, wait_for_version_negotiation, Timeout). +-spec open(ChannelPid, Name, Mode) -> {ok, Handle} | Error when + ChannelPid :: pid(), + Name :: string(), + Mode :: [read | write | append | binary | raw], + Handle :: term(), + Error :: {error, reason()} . open(Pid, File, Mode) -> open(Pid, File, Mode, ?FILEOP_TIMEOUT). +-spec open(ChannelPid, Name, Mode, Timeout) -> {ok, Handle} | Error when + ChannelPid :: pid(), + Name :: string(), + Mode :: [read | write | append | binary | raw], + Timeout :: timeout(), + Handle :: term(), + Error :: {error, reason()} . open(Pid, File, Mode, FileOpTimeout) -> call(Pid, {open, false, File, Mode}, FileOpTimeout). + +-type tar_crypto_spec() :: encrypt_spec() | decrypt_spec() . + +-type encrypt_spec() :: {init_fun(), crypto_fun(), final_fun()} . +-type decrypt_spec() :: {init_fun(), crypto_fun()} . + +-type init_fun() :: fun(() -> {ok,crypto_state()}) + | fun(() -> {ok,crypto_state(),chunk_size()}) . + +-type crypto_fun() :: fun((TextIn::binary(), crypto_state()) -> crypto_result()) . +-type crypto_result() :: {ok,TextOut::binary(),crypto_state()} + | {ok,TextOut::binary(),crypto_state(),chunk_size()} . + +-type final_fun() :: fun((FinalTextIn::binary(),crypto_state()) -> {ok,FinalTextOut::binary()}) . + +-type chunk_size() :: undefined | pos_integer(). +-type crypto_state() :: any() . + + +-spec open_tar(ChannelPid, Path, Mode) -> {ok, Handle} | Error when + ChannelPid :: pid(), + Path :: string(), + Mode :: [read | write | {crypto, tar_crypto_spec()} ], + Handle :: term(), + Error :: {error, reason()} . open_tar(Pid, File, Mode) -> open_tar(Pid, File, Mode, ?FILEOP_TIMEOUT). +-spec open_tar(ChannelPid, Path, Mode, Timeout) -> {ok, Handle} | Error when + ChannelPid :: pid(), + Path :: string(), + Mode :: [read | write | {crypto, tar_crypto_spec()} ], + Timeout :: timeout(), + Handle :: term(), + Error :: {error, reason()} . open_tar(Pid, File, Mode, FileOpTimeout) -> case {lists:member(write,Mode), lists:member(read,Mode), - Mode -- [read,write]} of + Mode -- [write,read]} of {true,false,[]} -> {ok,Handle} = open(Pid, File, [write], FileOpTimeout), erl_tar:init(Pid, write, @@ -264,13 +327,33 @@ open_tar(Pid, File, Mode, FileOpTimeout) -> end. +-spec opendir(ChannelPid, Path) -> {ok, Handle} | Error when + ChannelPid :: pid(), + Path :: string(), + Handle :: term(), + Error :: {error, reason()} . opendir(Pid, Path) -> opendir(Pid, Path, ?FILEOP_TIMEOUT). +-spec opendir(ChannelPid, Path, Timeout) -> {ok, Handle} | Error when + ChannelPid :: pid(), + Path :: string(), + Timeout :: timeout(), + Handle :: term(), + Error :: {error, reason()} . opendir(Pid, Path, FileOpTimeout) -> call(Pid, {opendir, false, Path}, FileOpTimeout). +-spec close(ChannelPid, Handle) -> ok | Error when + ChannelPid :: pid(), + Handle :: term(), + Error :: {error, reason()} . close(Pid, Handle) -> close(Pid, Handle, ?FILEOP_TIMEOUT). +-spec close(ChannelPid, Handle, Timeout) -> ok | Error when + ChannelPid :: pid(), + Handle :: term(), + Timeout :: timeout(), + Error :: {error, reason()} . close(Pid, Handle, FileOpTimeout) -> call(Pid, {close,false,Handle}, FileOpTimeout). @@ -279,47 +362,149 @@ readdir(Pid,Handle) -> readdir(Pid,Handle, FileOpTimeout) -> call(Pid, {readdir,false,Handle}, FileOpTimeout). +-spec pread(ChannelPid, Handle, Position, Len) -> {ok, Data} | eof | Error when + ChannelPid :: pid(), + Handle :: term(), + Position :: integer(), + Len :: integer(), + Data :: string() | binary(), + Error :: {error, reason()}. pread(Pid, Handle, Offset, Len) -> pread(Pid, Handle, Offset, Len, ?FILEOP_TIMEOUT). + +-spec pread(ChannelPid, Handle, Position, Len, Timeout) -> {ok, Data} | eof | Error when + ChannelPid :: pid(), + Handle :: term(), + Position :: integer(), + Len :: integer(), + Timeout :: timeout(), + Data :: string() | binary(), + Error :: {error, reason()}. pread(Pid, Handle, Offset, Len, FileOpTimeout) -> call(Pid, {pread,false,Handle, Offset, Len}, FileOpTimeout). + +-spec read(ChannelPid, Handle, Len) -> {ok, Data} | eof | Error when + ChannelPid :: pid(), + Handle :: term(), + Len :: integer(), + Data :: string() | binary(), + Error :: {error, reason()}. read(Pid, Handle, Len) -> read(Pid, Handle, Len, ?FILEOP_TIMEOUT). + +-spec read(ChannelPid, Handle, Len, Timeout) -> {ok, Data} | eof | Error when + ChannelPid :: pid(), + Handle :: term(), + Len :: integer(), + Timeout :: timeout(), + Data :: string() | binary(), + Error :: {error, reason()}. read(Pid, Handle, Len, FileOpTimeout) -> call(Pid, {read,false,Handle, Len}, FileOpTimeout). + %% TODO this ought to be a cast! Is so in all practical meaning %% even if it is obscure! +-spec apread(ChannelPid, Handle, Position, Len) -> {async, N} | Error when + ChannelPid :: pid(), + Handle :: term(), + Position :: integer(), + Len :: integer(), + Error :: {error, reason()}, + N :: term() . apread(Pid, Handle, Offset, Len) -> call(Pid, {pread,true,Handle, Offset, Len}, infinity). %% TODO this ought to be a cast! +-spec aread(ChannelPid, Handle, Len) -> {async, N} | Error when + ChannelPid :: pid(), + Handle :: term(), + Len :: integer(), + Error :: {error, reason()}, + N :: term() . aread(Pid, Handle, Len) -> call(Pid, {read,true,Handle, Len}, infinity). + +-spec pwrite(ChannelPid, Handle, Position, Data) -> ok | Error when + ChannelPid :: pid(), + Handle :: term(), + Position :: integer(), + Data :: iolist(), + Error :: {error, reason()}. pwrite(Pid, Handle, Offset, Data) -> pwrite(Pid, Handle, Offset, Data, ?FILEOP_TIMEOUT). + +-spec pwrite(ChannelPid, Handle, Position, Data, Timeout) -> ok | Error when + ChannelPid :: pid(), + Handle :: term(), + Position :: integer(), + Data :: iolist(), + Timeout :: timeout(), + Error :: {error, reason()}. pwrite(Pid, Handle, Offset, Data, FileOpTimeout) -> call(Pid, {pwrite,false,Handle,Offset,Data}, FileOpTimeout). + +-spec write(ChannelPid, Handle, Data) -> ok | Error when + ChannelPid :: pid(), + Handle :: term(), + Data :: iodata(), + Error :: {error, reason()}. write(Pid, Handle, Data) -> write(Pid, Handle, Data, ?FILEOP_TIMEOUT). + +-spec write(ChannelPid, Handle, Data, Timeout) -> ok | Error when + ChannelPid :: pid(), + Handle :: term(), + Data :: iodata(), + Timeout :: timeout(), + Error :: {error, reason()}. write(Pid, Handle, Data, FileOpTimeout) -> call(Pid, {write,false,Handle,Data}, FileOpTimeout). %% TODO this ought to be a cast! Is so in all practical meaning %% even if it is obscure! +-spec apwrite(ChannelPid, Handle, Position, Data) -> {async, N} | Error when + ChannelPid :: pid(), + Handle :: term(), + Position :: integer(), + Data :: binary(), + Error :: {error, reason()}, + N :: term() . apwrite(Pid, Handle, Offset, Data) -> call(Pid, {pwrite,true,Handle,Offset,Data}, infinity). %% TODO this ought to be a cast! Is so in all practical meaning %% even if it is obscure! +-spec awrite(ChannelPid, Handle, Data) -> {async, N} | Error when + ChannelPid :: pid(), + Handle :: term(), + Data :: binary(), + Error :: {error, reason()}, + N :: term() . awrite(Pid, Handle, Data) -> call(Pid, {write,true,Handle,Data}, infinity). +-spec position(ChannelPid, Handle, Location) -> {ok, NewPosition} | Error when + ChannelPid :: pid(), + Handle :: term(), + Location :: Offset | {bof, Offset} | {cur, Offset} | {eof, Offset} | bof | cur | eof, + Offset :: integer(), + NewPosition :: integer(), + Error :: {error, reason()}. position(Pid, Handle, Pos) -> position(Pid, Handle, Pos, ?FILEOP_TIMEOUT). + +-spec position(ChannelPid, Handle, Location, Timeout) -> {ok, NewPosition} | Error when + ChannelPid :: pid(), + Handle :: term(), + Location :: Offset | {bof, Offset} | {cur, Offset} | {eof, Offset} | bof | cur | eof, + Timeout :: timeout(), + Offset :: integer(), + NewPosition :: integer(), + Error :: {error, reason()}. position(Pid, Handle, Pos, FileOpTimeout) -> call(Pid, {position, Handle, Pos}, FileOpTimeout). @@ -328,8 +513,21 @@ real_path(Pid, Path) -> real_path(Pid, Path, FileOpTimeout) -> call(Pid, {real_path, false, Path}, FileOpTimeout). + +-spec read_file_info(ChannelPid, Name) -> {ok, FileInfo} | Error when + ChannelPid :: pid(), + Name :: string(), + FileInfo :: file:file_info(), + Error :: {error, reason()}. read_file_info(Pid, Name) -> read_file_info(Pid, Name, ?FILEOP_TIMEOUT). + +-spec read_file_info(ChannelPid, Name, Timeout) -> {ok, FileInfo} | Error when + ChannelPid :: pid(), + Name :: string(), + Timeout :: timeout(), + FileInfo :: file:file_info(), + Error :: {error, reason()}. read_file_info(Pid, Name, FileOpTimeout) -> call(Pid, {read_file_info,false,Name}, FileOpTimeout). @@ -338,18 +536,57 @@ get_file_info(Pid, Handle) -> get_file_info(Pid, Handle, FileOpTimeout) -> call(Pid, {get_file_info,false,Handle}, FileOpTimeout). + +-spec write_file_info(ChannelPid, Name, FileInfo) -> ok | Error when + ChannelPid :: pid(), + Name :: string(), + FileInfo :: file:file_info(), + Error :: {error, reason()}. write_file_info(Pid, Name, Info) -> write_file_info(Pid, Name, Info, ?FILEOP_TIMEOUT). + +-spec write_file_info(ChannelPid, Name, FileInfo, Timeout) -> ok | Error when + ChannelPid :: pid(), + Name :: string(), + FileInfo :: file:file_info(), + Timeout :: timeout(), + Error :: {error, reason()}. write_file_info(Pid, Name, Info, FileOpTimeout) -> call(Pid, {write_file_info,false,Name, Info}, FileOpTimeout). + +-spec read_link_info(ChannelPid, Name) -> {ok, FileInfo} | Error when + ChannelPid :: pid(), + Name :: string(), + FileInfo :: file:file_info(), + Error :: {error, reason()}. read_link_info(Pid, Name) -> read_link_info(Pid, Name, ?FILEOP_TIMEOUT). + +-spec read_link_info(ChannelPid, Name, Timeout) -> {ok, FileInfo} | Error when + ChannelPid :: pid(), + Name :: string(), + FileInfo :: file:file_info(), + Timeout :: timeout(), + Error :: {error, reason()}. read_link_info(Pid, Name, FileOpTimeout) -> call(Pid, {read_link_info,false,Name}, FileOpTimeout). + +-spec read_link(ChannelPid, Name) -> {ok, Target} | Error when + ChannelPid :: pid(), + Name :: string(), + Target :: string(), + Error :: {error, reason()}. read_link(Pid, LinkName) -> read_link(Pid, LinkName, ?FILEOP_TIMEOUT). + +-spec read_link(ChannelPid, Name, Timeout) -> {ok, Target} | Error when + ChannelPid :: pid(), + Name :: string(), + Target :: string(), + Timeout :: timeout(), + Error :: {error, reason()}. read_link(Pid, LinkName, FileOpTimeout) -> case call(Pid, {read_link,false,LinkName}, FileOpTimeout) of {ok, [{Name, _Attrs}]} -> @@ -358,28 +595,79 @@ read_link(Pid, LinkName, FileOpTimeout) -> ErrMsg end. +-spec make_symlink(ChannelPid, Name, Target) -> ok | Error when + ChannelPid :: pid(), + Name :: string(), + Target :: string(), + Error :: {error, reason()} . make_symlink(Pid, Name, Target) -> make_symlink(Pid, Name, Target, ?FILEOP_TIMEOUT). +-spec make_symlink(ChannelPid, Name, Target, Timeout) -> ok | Error when + ChannelPid :: pid(), + Name :: string(), + Target :: string(), + Timeout :: timeout(), + Error :: {error, reason()} . make_symlink(Pid, Name, Target, FileOpTimeout) -> call(Pid, {make_symlink,false, Name, Target}, FileOpTimeout). + +-spec rename(ChannelPid, OldName, NewName) -> ok | Error when + ChannelPid :: pid(), + OldName :: string(), + NewName :: string(), + Error :: {error, reason()}. rename(Pid, FromFile, ToFile) -> rename(Pid, FromFile, ToFile, ?FILEOP_TIMEOUT). + +-spec rename(ChannelPid, OldName, NewName, Timeout) -> ok | Error when + ChannelPid :: pid(), + OldName :: string(), + NewName :: string(), + Timeout :: timeout(), + Error :: {error, reason()}. rename(Pid, FromFile, ToFile, FileOpTimeout) -> call(Pid, {rename,false,FromFile, ToFile}, FileOpTimeout). +-spec delete(ChannelPid, Name) -> ok | Error when + ChannelPid :: pid(), + Name :: string(), + Error :: {error, reason()} . delete(Pid, Name) -> delete(Pid, Name, ?FILEOP_TIMEOUT). +-spec delete(ChannelPid, Name, Timeout) -> ok | Error when + ChannelPid :: pid(), + Name :: string(), + Timeout :: timeout(), + Error :: {error, reason()} . delete(Pid, Name, FileOpTimeout) -> call(Pid, {delete,false,Name}, FileOpTimeout). +-spec make_dir(ChannelPid, Name) -> ok | Error when + ChannelPid :: pid(), + Name :: string(), + Error :: {error, reason()} . make_dir(Pid, Name) -> make_dir(Pid, Name, ?FILEOP_TIMEOUT). +-spec make_dir(ChannelPid, Name, Timeout) -> ok | Error when + ChannelPid :: pid(), + Name :: string(), + Timeout :: timeout(), + Error :: {error, reason()} . make_dir(Pid, Name, FileOpTimeout) -> call(Pid, {make_dir,false,Name}, FileOpTimeout). +-spec del_dir(ChannelPid, Name) -> ok | Error when + ChannelPid :: pid(), + Name :: string(), + Error :: {error, reason()} . del_dir(Pid, Name) -> del_dir(Pid, Name, ?FILEOP_TIMEOUT). +-spec del_dir(ChannelPid, Name, Timeout) -> ok | Error when + ChannelPid :: pid(), + Name :: string(), + Timeout :: timeout(), + Error :: {error, reason()} . del_dir(Pid, Name, FileOpTimeout) -> call(Pid, {del_dir,false,Name}, FileOpTimeout). @@ -396,9 +684,21 @@ recv_window(Pid, FileOpTimeout) -> call(Pid, recv_window, FileOpTimeout). +-spec list_dir(ChannelPid, Path) -> {ok,FileNames} | Error when + ChannelPid :: pid(), + Path :: string(), + FileNames :: [FileName], + FileName :: string(), + Error :: {error, reason()} . list_dir(Pid, Name) -> list_dir(Pid, Name, ?FILEOP_TIMEOUT). - +-spec list_dir(ChannelPid, Path, Timeout) -> {ok,FileNames} | Error when + ChannelPid :: pid(), + Path :: string(), + Timeout :: timeout(), + FileNames :: [FileName], + FileName :: string(), + Error :: {error, reason()} . list_dir(Pid, Name, FileOpTimeout) -> case opendir(Pid, Name, FileOpTimeout) of {ok,Handle} -> @@ -429,9 +729,20 @@ do_list_dir(Pid, Handle, FileOpTimeout, Acc) -> end. +-spec read_file(ChannelPid, File) -> {ok, Data} | Error when + ChannelPid :: pid(), + File :: string(), + Data :: binary(), + Error :: {error, reason()}. read_file(Pid, Name) -> read_file(Pid, Name, ?FILEOP_TIMEOUT). +-spec read_file(ChannelPid, File, Timeout) -> {ok, Data} | Error when + ChannelPid :: pid(), + File :: string(), + Data :: binary(), + Timeout :: timeout(), + Error :: {error, reason()}. read_file(Pid, Name, FileOpTimeout) -> case open(Pid, Name, [read, binary], FileOpTimeout) of {ok, Handle} -> @@ -453,9 +764,20 @@ read_file_loop(Pid, Handle, PacketSz, FileOpTimeout, Acc) -> Error end. +-spec write_file(ChannelPid, File, Data) -> ok | Error when + ChannelPid :: pid(), + File :: string(), + Data :: iodata(), + Error :: {error, reason()}. write_file(Pid, Name, List) -> write_file(Pid, Name, List, ?FILEOP_TIMEOUT). +-spec write_file(ChannelPid, File, Data, Timeout) -> ok | Error when + ChannelPid :: pid(), + File :: string(), + Data :: iodata(), + Timeout :: timeout(), + Error :: {error, reason()}. write_file(Pid, Name, List, FileOpTimeout) when is_list(List) -> write_file(Pid, Name, list_to_binary(List), FileOpTimeout); write_file(Pid, Name, Bin, FileOpTimeout) -> -- cgit v1.2.3