From b3069dbb63bcdba437157911763073cbd62d40eb Mon Sep 17 00:00:00 2001
From: Ingela Anderton Andin <ingela@erlang.org>
Date: Wed, 21 Jan 2015 15:33:36 +0100
Subject: ssh: Add handling of sftp v3 flags

---
 lib/ssh/src/ssh_sftpd.erl        | 20 ++++++++++++++---
 lib/ssh/test/ssh_sftpd_SUITE.erl | 48 ++++++++++++++++++++++++++++++++++++++--
 2 files changed, 63 insertions(+), 5 deletions(-)

diff --git a/lib/ssh/src/ssh_sftpd.erl b/lib/ssh/src/ssh_sftpd.erl
index 52665635f0..5410bd1925 100644
--- a/lib/ssh/src/ssh_sftpd.erl
+++ b/lib/ssh/src/ssh_sftpd.erl
@@ -1,7 +1,7 @@
 %%
 %% %CopyrightBegin%
 %%
-%% Copyright Ericsson AB 2005-2013. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2015. All Rights Reserved.
 %%
 %% The contents of this file are subject to the Erlang Public License,
 %% Version 1.1, (the "License"); you may not use this file except in
@@ -558,7 +558,20 @@ stat(ReqId, RelPath, State0=#state{file_handler=FileMod,
 	{error, E} ->
 	    send_status({error, E}, ReqId, State1)
     end.
-
+%% sftp v3
+decode_4_open_flag(read) ->
+    [read];
+decode_4_open_flag(write) ->
+    [write];
+decode_4_open_flag(append) ->
+    [append];
+decode_4_open_flag(creat) ->
+    [write];
+decode_4_open_flag(trunc) ->
+    [write];
+decode_4_open_flag(excl) ->
+    [read];
+%% sftp newer 
 decode_4_open_flag(create_new) ->
     [write];
 decode_4_open_flag(create_truncate) ->
@@ -608,7 +621,8 @@ open(Vsn, ReqId, Data, State) when Vsn =< 3 ->
     <<?UINT32(BLen), BPath:BLen/binary, ?UINT32(PFlags),
      _Attrs/binary>> = Data,
     Path = unicode:characters_to_list(BPath),
-    Flags = ssh_xfer:decode_open_flags(Vsn, PFlags),
+    FlagBits = ssh_xfer:decode_open_flags(Vsn, PFlags),
+    Flags = lists:append(lists:umerge([[decode_4_flags(FlagBits)]])),
     do_open(ReqId, State, Path, Flags);
 open(Vsn, ReqId, Data, State) when Vsn >= 4 ->
     <<?UINT32(BLen), BPath:BLen/binary, ?UINT32(Access),
diff --git a/lib/ssh/test/ssh_sftpd_SUITE.erl b/lib/ssh/test/ssh_sftpd_SUITE.erl
index 7b22e45d5e..0ce8eec906 100644
--- a/lib/ssh/test/ssh_sftpd_SUITE.erl
+++ b/lib/ssh/test/ssh_sftpd_SUITE.erl
@@ -1,7 +1,7 @@
 %%
 %% %CopyrightBegin%
 %%
-%% Copyright Ericsson AB 2006-2013. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2015. All Rights Reserved.
 %%
 %% The contents of this file are subject to the Erlang Public License,
 %% Version 1.1, (the "License"); you may not use this file except in
@@ -56,7 +56,8 @@ all() ->
      retrieve_attributes, 
      set_attributes, 
      links,
-     ver3_rename, 
+     ver3_rename,
+     ver3_open_flags,
      relpath, 
      sshd_read_file,
      ver6_basic].
@@ -193,6 +194,39 @@ open_close_file(Config) when is_list(Config) ->
 		  ?ACE4_READ_DATA  bor ?ACE4_READ_ATTRIBUTES,
 		  ?SSH_FXF_OPEN_EXISTING).
 
+ver3_open_flags() ->
+    [{doc, "Test open flags"}].
+ver3_open_flags(Config) when is_list(Config) ->
+    PrivDir =  ?config(priv_dir, Config),
+    FileName = filename:join(PrivDir, "not_exist.txt"),
+    {Cm, Channel} = ?config(sftp, Config),
+    ReqId = 0,
+    
+    {ok, <<?SSH_FXP_HANDLE, ?UINT32(ReqId), Handle/binary>>, _} =
+	open_file_v3(FileName, Cm, Channel, ReqId,
+		     ?SSH_FXF_CREAT bor ?SSH_FXF_TRUNC),
+    {ok, <<?SSH_FXP_STATUS, ?UINT32(ReqId),
+	   ?UINT32(?SSH_FX_OK), _/binary>>, _} = close(Handle, ReqId,
+						       Cm, Channel),
+   
+    NewFileName = filename:join(PrivDir, "not_exist2.txt"),
+    NewReqId = ReqId + 1, 
+    {ok, <<?SSH_FXP_HANDLE, ?UINT32(NewReqId), NewHandle/binary>>, _} =
+     	open_file_v3(NewFileName, Cm, Channel, NewReqId,
+    		     ?SSH_FXF_CREAT bor ?SSH_FXF_EXCL),
+    {ok, <<?SSH_FXP_STATUS, ?UINT32(NewReqId),
+    	   ?UINT32(?SSH_FX_OK), _/binary>>, _} = close(NewHandle, NewReqId,
+    						       Cm, Channel),
+    
+    NewFileName1 = filename:join(PrivDir, "test.txt"),
+    NewReqId1 = NewReqId + 1,
+    {ok, <<?SSH_FXP_HANDLE, ?UINT32(NewReqId1), NewHandle1/binary>>, _} =
+	open_file_v3(NewFileName1, Cm, Channel, NewReqId1,
+		     ?SSH_FXF_READ bor ?SSH_FXF_WRITE bor ?SSH_FXF_APPEND),
+     {ok, <<?SSH_FXP_STATUS, ?UINT32(NewReqId1),
+	   ?UINT32(?SSH_FX_OK), _/binary>>, _} = close(NewHandle1, NewReqId1,
+						       Cm, Channel).
+    
 %%--------------------------------------------------------------------
 open_close_dir() ->
     [{doc,"Test SSH_FXP_OPENDIR and SSH_FXP_CLOSE commands"}].
@@ -662,6 +696,16 @@ open_file(File, Cm, Channel, ReqId, Access, Flags) ->
 				      ?SSH_FXP_OPEN, Data/binary>>),
     reply(Cm, Channel).
 
+open_file_v3(File, Cm, Channel, ReqId, Flags) ->
+
+    Data = list_to_binary([?uint32(ReqId),
+			   ?binary(list_to_binary(File)),
+			   ?uint32(Flags),
+			   ?REG_ATTERS]),
+    Size = 1 + size(Data),
+    ssh_connection:send(Cm, Channel, <<?UINT32(Size),
+				      ?SSH_FXP_OPEN, Data/binary>>),
+    reply(Cm, Channel).
 
 
 close(Handle, ReqId, Cm , Channel) ->
-- 
cgit v1.2.3


From ec6583db02ec4b629c6b6b06119d324daea42225 Mon Sep 17 00:00:00 2001
From: Ingela Anderton Andin <ingela@erlang.org>
Date: Thu, 22 Jan 2015 11:57:14 +0100
Subject: ssh: Correct Sftp flag handling

Function name was somewhat confusing and when trying to find a better
name for it we realised it did not work as intended.
---
 lib/ssh/src/ssh_sftpd.erl | 120 +++++++++++++++++++++++-----------------------
 1 file changed, 59 insertions(+), 61 deletions(-)

diff --git a/lib/ssh/src/ssh_sftpd.erl b/lib/ssh/src/ssh_sftpd.erl
index 5410bd1925..a4e3e46ca3 100644
--- a/lib/ssh/src/ssh_sftpd.erl
+++ b/lib/ssh/src/ssh_sftpd.erl
@@ -558,71 +558,70 @@ stat(ReqId, RelPath, State0=#state{file_handler=FileMod,
 	{error, E} ->
 	    send_status({error, E}, ReqId, State1)
     end.
-%% sftp v3
-decode_4_open_flag(read) ->
-    [read];
-decode_4_open_flag(write) ->
-    [write];
-decode_4_open_flag(append) ->
-    [append];
-decode_4_open_flag(creat) ->
-    [write];
-decode_4_open_flag(trunc) ->
-    [write];
-decode_4_open_flag(excl) ->
-    [read];
-%% sftp newer 
-decode_4_open_flag(create_new) ->
-    [write];
-decode_4_open_flag(create_truncate) ->
-    [write];
-decode_4_open_flag(truncate_existing) ->
-    [write];
-decode_4_open_flag(open_existing) ->
-    [read].
-
-decode_4_flags([OpenFlag | Flags]) ->
-    decode_4_flags(Flags, decode_4_open_flag(OpenFlag)).
-
-decode_4_flags([], Flags) ->
-    Flags;
-decode_4_flags([append_data|R], _Flags) ->
-    decode_4_flags(R, [append]);
-decode_4_flags([append_data_atomic|R], _Flags) ->
-    decode_4_flags(R, [append]);
-decode_4_flags([_|R], Flags) ->
-    decode_4_flags(R, Flags).
-
-decode_4_access_flag(read_data) ->
-    [read];
-decode_4_access_flag(list_directory) ->
-    [read];
-decode_4_access_flag(write_data) ->
-    [write];
-decode_4_access_flag(add_file) ->
-    [write];
-decode_4_access_flag(add_subdirectory) ->
-    [read];
-decode_4_access_flag(append_data) ->
-    [append];
-decode_4_access_flag(write_attributes) ->
-    [write];
-decode_4_access_flag(_) ->
-    [read].
-
-decode_4_acess([_ | _] = Flags) ->
+
+sftp_to_erlang_flag(read, Vsn) when Vsn == 3;
+				    Vsn == 4 ->
+    read;
+sftp_to_erlang_flag(write, Vsn) when Vsn == 3;
+				     Vsn == 4 ->
+    write;
+sftp_to_erlang_flag(append, Vsn) when Vsn == 3;
+				      Vsn == 4 ->
+    append;
+sftp_to_erlang_flag(creat, Vsn) when Vsn == 3;
+				     Vsn == 4 ->
+    write;
+sftp_to_erlang_flag(trunc, Vsn) when Vsn == 3;
+				     Vsn == 4 ->
+    write;
+sftp_to_erlang_flag(excl, Vsn) when Vsn == 3;
+				    Vsn == 4 ->
+    read;
+sftp_to_erlang_flag(append_data, Vsn)  when Vsn > 4 ->
+    append;
+sftp_to_erlang_flag(append_data_atomic, Vsn) when Vsn > 4  ->
+    append;
+sftp_to_erlang_flag(create_new, Vsn)  when Vsn > 4 ->
+    write;
+sftp_to_erlang_flag(create_truncate, Vsn) when Vsn > 4 ->
+    write;
+sftp_to_erlang_flag(truncate_existing, Vsn) when Vsn > 4 ->
+    write;
+sftp_to_erlang_flag(open_existing, Vsn)  when Vsn > 4 ->
+    read.
+
+sftp_to_erlang_flags(Flags, Vsn) ->
+    lists:map(fun(Flag) -> 
+		      sftp_to_erlang_flag(Flag, Vsn) 
+	      end, Flags).
+
+sftp_to_erlang_access_flag(read_data, _) ->
+    read;
+sftp_to_erlang_access_flag(list_directory, _) ->
+    read;
+sftp_to_erlang_access_flag(write_data, _) ->
+    write;
+sftp_to_erlang_access_flag(add_file, _) ->
+    write;
+sftp_to_erlang_access_flag(add_subdirectory, _) ->
+    read;
+sftp_to_erlang_access_flag(append_data, _) ->
+    append;
+sftp_to_erlang_access_flag(write_attributes, _) ->
+    write;
+sftp_to_erlang_access_flag(_, _) ->
+    read.
+sftp_to_erlang_access_flags(Flags, Vsn) ->
     lists:map(fun(Flag) -> 
-		      [decode_4_access_flag(Flag)]
-	      end, Flags);
-decode_4_acess([]) ->
-    [].
+		      sftp_to_erlang_access_flag(Flag, Vsn)
+	      end, Flags).
 
 open(Vsn, ReqId, Data, State) when Vsn =< 3 ->
     <<?UINT32(BLen), BPath:BLen/binary, ?UINT32(PFlags),
      _Attrs/binary>> = Data,
     Path = unicode:characters_to_list(BPath),
     FlagBits = ssh_xfer:decode_open_flags(Vsn, PFlags),
-    Flags = lists:append(lists:umerge([[decode_4_flags(FlagBits)]])),
+    Flags = lists:usort(sftp_to_erlang_flags(FlagBits, Vsn)),
     do_open(ReqId, State, Path, Flags);
 open(Vsn, ReqId, Data, State) when Vsn >= 4 ->
     <<?UINT32(BLen), BPath:BLen/binary, ?UINT32(Access),
@@ -636,9 +635,8 @@ open(Vsn, ReqId, Data, State) when Vsn >= 4 ->
     %% it works better than when the Access flags where totally ignored.
     %% A better solution may need some code refactoring that we do
     %% not have time for right now.
-    AcessFlags = decode_4_acess(AcessBits),
-    Flags = lists:append(lists:umerge(
-			   [[decode_4_flags(FlagBits)] | AcessFlags])),
+    AcessFlags = sftp_to_erlang_access_flags(AcessBits, Vsn),
+    Flags = lists:usort(sftp_to_erlang_flags(FlagBits, Vsn) ++ AcessFlags),
     do_open(ReqId, State, Path, Flags).
 
 do_open(ReqId, State0, Path, Flags) ->
-- 
cgit v1.2.3


From 5c1a83668b14ef4288adaf181140f7f325ca407f Mon Sep 17 00:00:00 2001
From: Ingela Anderton Andin <ingela@erlang.org>
Date: Fri, 23 Jan 2015 09:41:05 +0100
Subject: ssh: Add some more flags

---
 lib/ssh/src/ssh_sftpd.erl | 32 +++++++++++++++++---------------
 1 file changed, 17 insertions(+), 15 deletions(-)

diff --git a/lib/ssh/src/ssh_sftpd.erl b/lib/ssh/src/ssh_sftpd.erl
index a4e3e46ca3..04ae6b11e2 100644
--- a/lib/ssh/src/ssh_sftpd.erl
+++ b/lib/ssh/src/ssh_sftpd.erl
@@ -577,17 +577,21 @@ sftp_to_erlang_flag(trunc, Vsn) when Vsn == 3;
 sftp_to_erlang_flag(excl, Vsn) when Vsn == 3;
 				    Vsn == 4 ->
     read;
-sftp_to_erlang_flag(append_data, Vsn)  when Vsn > 4 ->
-    append;
-sftp_to_erlang_flag(append_data_atomic, Vsn) when Vsn > 4  ->
-    append;
 sftp_to_erlang_flag(create_new, Vsn)  when Vsn > 4 ->
     write;
 sftp_to_erlang_flag(create_truncate, Vsn) when Vsn > 4 ->
     write;
+sftp_to_erlang_flag(open_existing, Vsn)  when Vsn > 4 ->
+    read;
+sftp_to_erlang_flag(open_or_create, Vsn) when Vsn > 4 ->
+    write;
 sftp_to_erlang_flag(truncate_existing, Vsn) when Vsn > 4 ->
     write;
-sftp_to_erlang_flag(open_existing, Vsn)  when Vsn > 4 ->
+sftp_to_erlang_flag(append_data, Vsn)  when Vsn > 4 ->
+    append;
+sftp_to_erlang_flag(append_data_atomic, Vsn) when Vsn > 4  ->
+    append;
+sftp_to_erlang_flag(_, _) ->
     read.
 
 sftp_to_erlang_flags(Flags, Vsn) ->
@@ -601,12 +605,12 @@ sftp_to_erlang_access_flag(list_directory, _) ->
     read;
 sftp_to_erlang_access_flag(write_data, _) ->
     write;
-sftp_to_erlang_access_flag(add_file, _) ->
-    write;
-sftp_to_erlang_access_flag(add_subdirectory, _) ->
-    read;
 sftp_to_erlang_access_flag(append_data, _) ->
     append;
+sftp_to_erlang_access_flag(add_subdirectory, _) ->
+    read;
+sftp_to_erlang_access_flag(add_file, _) ->
+    write;
 sftp_to_erlang_access_flag(write_attributes, _) ->
     write;
 sftp_to_erlang_access_flag(_, _) ->
@@ -629,12 +633,10 @@ open(Vsn, ReqId, Data, State) when Vsn >= 4 ->
     Path = unicode:characters_to_list(BPath),
     FlagBits = ssh_xfer:decode_open_flags(Vsn, PFlags),
     AcessBits = ssh_xfer:decode_ace_mask(Access),
-    %% TODO: This is to make sure the Access flags are not ignored
-    %% but this should be thought through better. This solution should
-    %% be considered a hack in order to buy some time. At least
-    %% it works better than when the Access flags where totally ignored.
-    %% A better solution may need some code refactoring that we do
-    %% not have time for right now.
+    %% TODO: There are still flags that are not
+    %% fully handled as SSH_FXF_ACCESS_TEXT_MODE and
+    %% a lot a ACE flags, the later we may not need 
+    %% to understand as they are NFS flags
     AcessFlags = sftp_to_erlang_access_flags(AcessBits, Vsn),
     Flags = lists:usort(sftp_to_erlang_flags(FlagBits, Vsn) ++ AcessFlags),
     do_open(ReqId, State, Path, Flags).
-- 
cgit v1.2.3