diff options
author | Pavel Shilovsky <piastry@etersoft.ru> | 2011-12-26 13:58:46 -0500 |
---|---|---|
committer | Pavel Shilovsky <pshilovsky@samba.org> | 2012-07-24 13:55:05 -0400 |
commit | 2503a0dba989486c59523a947a1dcb50ad90fee9 (patch) | |
tree | 1e79a740d744cee1a1981e4d0a355303ffc9a4d2 /fs/cifs/smb2pdu.c | |
parent | 68889f269b16a11866f4ec71e8177bdd0c184a3f (diff) |
CIFS: Add SMB2 support for is_path_accessible
that needs for a successful mount through SMB2 protocol.
Signed-off-by: Pavel Shilovsky <piastry@etersoft.ru>
Signed-off-by: Steve French <smfrench@gmail.com>
Diffstat (limited to 'fs/cifs/smb2pdu.c')
-rw-r--r-- | fs/cifs/smb2pdu.c | 132 |
1 files changed, 132 insertions, 0 deletions
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c index 48c04b2832e2..ef0769c398a5 100644 --- a/fs/cifs/smb2pdu.c +++ b/fs/cifs/smb2pdu.c | |||
@@ -829,3 +829,135 @@ SMB2_tdis(const unsigned int xid, struct cifs_tcon *tcon) | |||
829 | 829 | ||
830 | return rc; | 830 | return rc; |
831 | } | 831 | } |
832 | |||
833 | int | ||
834 | SMB2_open(const unsigned int xid, struct cifs_tcon *tcon, __le16 *path, | ||
835 | u64 *persistent_fid, u64 *volatile_fid, __u32 desired_access, | ||
836 | __u32 create_disposition, __u32 file_attributes, __u32 create_options) | ||
837 | { | ||
838 | struct smb2_create_req *req; | ||
839 | struct smb2_create_rsp *rsp; | ||
840 | struct TCP_Server_Info *server; | ||
841 | struct cifs_ses *ses = tcon->ses; | ||
842 | struct kvec iov[2]; | ||
843 | int resp_buftype; | ||
844 | int uni_path_len; | ||
845 | int rc = 0; | ||
846 | int num_iovecs = 2; | ||
847 | |||
848 | cFYI(1, "create/open"); | ||
849 | |||
850 | if (ses && (ses->server)) | ||
851 | server = ses->server; | ||
852 | else | ||
853 | return -EIO; | ||
854 | |||
855 | rc = small_smb2_init(SMB2_CREATE, tcon, (void **) &req); | ||
856 | if (rc) | ||
857 | return rc; | ||
858 | |||
859 | if (enable_oplocks) | ||
860 | req->RequestedOplockLevel = SMB2_OPLOCK_LEVEL_BATCH; | ||
861 | else | ||
862 | req->RequestedOplockLevel = SMB2_OPLOCK_LEVEL_NONE; | ||
863 | req->ImpersonationLevel = IL_IMPERSONATION; | ||
864 | req->DesiredAccess = cpu_to_le32(desired_access); | ||
865 | /* File attributes ignored on open (used in create though) */ | ||
866 | req->FileAttributes = cpu_to_le32(file_attributes); | ||
867 | req->ShareAccess = FILE_SHARE_ALL_LE; | ||
868 | req->CreateDisposition = cpu_to_le32(create_disposition); | ||
869 | req->CreateOptions = cpu_to_le32(create_options); | ||
870 | uni_path_len = (2 * UniStrnlen((wchar_t *)path, PATH_MAX)) + 2; | ||
871 | req->NameOffset = cpu_to_le16(sizeof(struct smb2_create_req) | ||
872 | - 1 /* pad */ - 4 /* do not count rfc1001 len field */); | ||
873 | |||
874 | iov[0].iov_base = (char *)req; | ||
875 | /* 4 for rfc1002 length field */ | ||
876 | iov[0].iov_len = get_rfc1002_length(req) + 4; | ||
877 | |||
878 | /* MUST set path len (NameLength) to 0 opening root of share */ | ||
879 | if (uni_path_len >= 4) { | ||
880 | req->NameLength = cpu_to_le16(uni_path_len - 2); | ||
881 | /* -1 since last byte is buf[0] which is sent below (path) */ | ||
882 | iov[0].iov_len--; | ||
883 | iov[1].iov_len = uni_path_len; | ||
884 | iov[1].iov_base = path; | ||
885 | /* | ||
886 | * -1 since last byte is buf[0] which was counted in | ||
887 | * smb2_buf_len. | ||
888 | */ | ||
889 | inc_rfc1001_len(req, uni_path_len - 1); | ||
890 | } else { | ||
891 | num_iovecs = 1; | ||
892 | req->NameLength = 0; | ||
893 | } | ||
894 | |||
895 | rc = SendReceive2(xid, ses, iov, num_iovecs, &resp_buftype, 0); | ||
896 | rsp = (struct smb2_create_rsp *)iov[0].iov_base; | ||
897 | |||
898 | if (rc != 0) { | ||
899 | cifs_stats_fail_inc(tcon, SMB2_CREATE_HE); | ||
900 | goto creat_exit; | ||
901 | } | ||
902 | |||
903 | if (rsp == NULL) { | ||
904 | rc = -EIO; | ||
905 | goto creat_exit; | ||
906 | } | ||
907 | *persistent_fid = rsp->PersistentFileId; | ||
908 | *volatile_fid = rsp->VolatileFileId; | ||
909 | creat_exit: | ||
910 | free_rsp_buf(resp_buftype, rsp); | ||
911 | return rc; | ||
912 | } | ||
913 | |||
914 | int | ||
915 | SMB2_close(const unsigned int xid, struct cifs_tcon *tcon, | ||
916 | u64 persistent_fid, u64 volatile_fid) | ||
917 | { | ||
918 | struct smb2_close_req *req; | ||
919 | struct smb2_close_rsp *rsp; | ||
920 | struct TCP_Server_Info *server; | ||
921 | struct cifs_ses *ses = tcon->ses; | ||
922 | struct kvec iov[1]; | ||
923 | int resp_buftype; | ||
924 | int rc = 0; | ||
925 | |||
926 | cFYI(1, "Close"); | ||
927 | |||
928 | if (ses && (ses->server)) | ||
929 | server = ses->server; | ||
930 | else | ||
931 | return -EIO; | ||
932 | |||
933 | rc = small_smb2_init(SMB2_CLOSE, tcon, (void **) &req); | ||
934 | if (rc) | ||
935 | return rc; | ||
936 | |||
937 | req->PersistentFileId = persistent_fid; | ||
938 | req->VolatileFileId = volatile_fid; | ||
939 | |||
940 | iov[0].iov_base = (char *)req; | ||
941 | /* 4 for rfc1002 length field */ | ||
942 | iov[0].iov_len = get_rfc1002_length(req) + 4; | ||
943 | |||
944 | rc = SendReceive2(xid, ses, iov, 1, &resp_buftype, 0); | ||
945 | rsp = (struct smb2_close_rsp *)iov[0].iov_base; | ||
946 | |||
947 | if (rc != 0) { | ||
948 | if (tcon) | ||
949 | cifs_stats_fail_inc(tcon, SMB2_CLOSE_HE); | ||
950 | goto close_exit; | ||
951 | } | ||
952 | |||
953 | if (rsp == NULL) { | ||
954 | rc = -EIO; | ||
955 | goto close_exit; | ||
956 | } | ||
957 | |||
958 | /* BB FIXME - decode close response, update inode for caching */ | ||
959 | |||
960 | close_exit: | ||
961 | free_rsp_buf(resp_buftype, rsp); | ||
962 | return rc; | ||
963 | } | ||