diff options
Diffstat (limited to 'fs/cifs/cifssmb.c')
-rw-r--r-- | fs/cifs/cifssmb.c | 159 |
1 files changed, 117 insertions, 42 deletions
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index d06260251c30..1866bc2927d4 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c | |||
@@ -524,8 +524,8 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) | |||
524 | int val, seconds, remain, result; | 524 | int val, seconds, remain, result; |
525 | struct timespec ts, utc; | 525 | struct timespec ts, utc; |
526 | utc = CURRENT_TIME; | 526 | utc = CURRENT_TIME; |
527 | ts = cnvrtDosUnixTm(le16_to_cpu(rsp->SrvTime.Date), | 527 | ts = cnvrtDosUnixTm(rsp->SrvTime.Date, |
528 | le16_to_cpu(rsp->SrvTime.Time)); | 528 | rsp->SrvTime.Time, 0); |
529 | cFYI(1, ("SrvTime %d sec since 1970 (utc: %d) diff: %d", | 529 | cFYI(1, ("SrvTime %d sec since 1970 (utc: %d) diff: %d", |
530 | (int)ts.tv_sec, (int)utc.tv_sec, | 530 | (int)ts.tv_sec, (int)utc.tv_sec, |
531 | (int)(utc.tv_sec - ts.tv_sec))); | 531 | (int)(utc.tv_sec - ts.tv_sec))); |
@@ -594,7 +594,7 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) | |||
594 | else if (secFlags & CIFSSEC_MAY_KRB5) | 594 | else if (secFlags & CIFSSEC_MAY_KRB5) |
595 | server->secType = Kerberos; | 595 | server->secType = Kerberos; |
596 | else if (secFlags & CIFSSEC_MAY_NTLMSSP) | 596 | else if (secFlags & CIFSSEC_MAY_NTLMSSP) |
597 | server->secType = NTLMSSP; | 597 | server->secType = RawNTLMSSP; |
598 | else if (secFlags & CIFSSEC_MAY_LANMAN) | 598 | else if (secFlags & CIFSSEC_MAY_LANMAN) |
599 | server->secType = LANMAN; | 599 | server->secType = LANMAN; |
600 | /* #ifdef CONFIG_CIFS_EXPERIMENTAL | 600 | /* #ifdef CONFIG_CIFS_EXPERIMENTAL |
@@ -729,7 +729,7 @@ CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon) | |||
729 | * the tcon is no longer on the list, so no need to take lock before | 729 | * the tcon is no longer on the list, so no need to take lock before |
730 | * checking this. | 730 | * checking this. |
731 | */ | 731 | */ |
732 | if (tcon->need_reconnect) | 732 | if ((tcon->need_reconnect) || (tcon->ses->need_reconnect)) |
733 | return 0; | 733 | return 0; |
734 | 734 | ||
735 | rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon, | 735 | rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon, |
@@ -1113,7 +1113,10 @@ PsxCreat: | |||
1113 | psx_create_err: | 1113 | psx_create_err: |
1114 | cifs_buf_release(pSMB); | 1114 | cifs_buf_release(pSMB); |
1115 | 1115 | ||
1116 | cifs_stats_inc(&tcon->num_mkdirs); | 1116 | if (posix_flags & SMB_O_DIRECTORY) |
1117 | cifs_stats_inc(&tcon->num_posixmkdirs); | ||
1118 | else | ||
1119 | cifs_stats_inc(&tcon->num_posixopens); | ||
1117 | 1120 | ||
1118 | if (rc == -EAGAIN) | 1121 | if (rc == -EAGAIN) |
1119 | goto PsxCreat; | 1122 | goto PsxCreat; |
@@ -2427,8 +2430,7 @@ querySymLinkRetry: | |||
2427 | params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ; | 2430 | params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ; |
2428 | pSMB->TotalDataCount = 0; | 2431 | pSMB->TotalDataCount = 0; |
2429 | pSMB->MaxParameterCount = cpu_to_le16(2); | 2432 | pSMB->MaxParameterCount = cpu_to_le16(2); |
2430 | /* BB find exact max data count below from sess structure BB */ | 2433 | pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize); |
2431 | pSMB->MaxDataCount = cpu_to_le16(4000); | ||
2432 | pSMB->MaxSetupCount = 0; | 2434 | pSMB->MaxSetupCount = 0; |
2433 | pSMB->Reserved = 0; | 2435 | pSMB->Reserved = 0; |
2434 | pSMB->Flags = 0; | 2436 | pSMB->Flags = 0; |
@@ -5075,10 +5077,114 @@ SetAttrLgcyRetry: | |||
5075 | } | 5077 | } |
5076 | #endif /* temporarily unneeded SetAttr legacy function */ | 5078 | #endif /* temporarily unneeded SetAttr legacy function */ |
5077 | 5079 | ||
5080 | static void | ||
5081 | cifs_fill_unix_set_info(FILE_UNIX_BASIC_INFO *data_offset, | ||
5082 | const struct cifs_unix_set_info_args *args) | ||
5083 | { | ||
5084 | u64 mode = args->mode; | ||
5085 | |||
5086 | /* | ||
5087 | * Samba server ignores set of file size to zero due to bugs in some | ||
5088 | * older clients, but we should be precise - we use SetFileSize to | ||
5089 | * set file size and do not want to truncate file size to zero | ||
5090 | * accidently as happened on one Samba server beta by putting | ||
5091 | * zero instead of -1 here | ||
5092 | */ | ||
5093 | data_offset->EndOfFile = cpu_to_le64(NO_CHANGE_64); | ||
5094 | data_offset->NumOfBytes = cpu_to_le64(NO_CHANGE_64); | ||
5095 | data_offset->LastStatusChange = cpu_to_le64(args->ctime); | ||
5096 | data_offset->LastAccessTime = cpu_to_le64(args->atime); | ||
5097 | data_offset->LastModificationTime = cpu_to_le64(args->mtime); | ||
5098 | data_offset->Uid = cpu_to_le64(args->uid); | ||
5099 | data_offset->Gid = cpu_to_le64(args->gid); | ||
5100 | /* better to leave device as zero when it is */ | ||
5101 | data_offset->DevMajor = cpu_to_le64(MAJOR(args->device)); | ||
5102 | data_offset->DevMinor = cpu_to_le64(MINOR(args->device)); | ||
5103 | data_offset->Permissions = cpu_to_le64(mode); | ||
5104 | |||
5105 | if (S_ISREG(mode)) | ||
5106 | data_offset->Type = cpu_to_le32(UNIX_FILE); | ||
5107 | else if (S_ISDIR(mode)) | ||
5108 | data_offset->Type = cpu_to_le32(UNIX_DIR); | ||
5109 | else if (S_ISLNK(mode)) | ||
5110 | data_offset->Type = cpu_to_le32(UNIX_SYMLINK); | ||
5111 | else if (S_ISCHR(mode)) | ||
5112 | data_offset->Type = cpu_to_le32(UNIX_CHARDEV); | ||
5113 | else if (S_ISBLK(mode)) | ||
5114 | data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV); | ||
5115 | else if (S_ISFIFO(mode)) | ||
5116 | data_offset->Type = cpu_to_le32(UNIX_FIFO); | ||
5117 | else if (S_ISSOCK(mode)) | ||
5118 | data_offset->Type = cpu_to_le32(UNIX_SOCKET); | ||
5119 | } | ||
5120 | |||
5078 | int | 5121 | int |
5079 | CIFSSMBUnixSetInfo(const int xid, struct cifsTconInfo *tcon, char *fileName, | 5122 | CIFSSMBUnixSetFileInfo(const int xid, struct cifsTconInfo *tcon, |
5080 | const struct cifs_unix_set_info_args *args, | 5123 | const struct cifs_unix_set_info_args *args, |
5081 | const struct nls_table *nls_codepage, int remap) | 5124 | u16 fid, u32 pid_of_opener) |
5125 | { | ||
5126 | struct smb_com_transaction2_sfi_req *pSMB = NULL; | ||
5127 | FILE_UNIX_BASIC_INFO *data_offset; | ||
5128 | int rc = 0; | ||
5129 | u16 params, param_offset, offset, byte_count, count; | ||
5130 | |||
5131 | cFYI(1, ("Set Unix Info (via SetFileInfo)")); | ||
5132 | rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB); | ||
5133 | |||
5134 | if (rc) | ||
5135 | return rc; | ||
5136 | |||
5137 | pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener); | ||
5138 | pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16)); | ||
5139 | |||
5140 | params = 6; | ||
5141 | pSMB->MaxSetupCount = 0; | ||
5142 | pSMB->Reserved = 0; | ||
5143 | pSMB->Flags = 0; | ||
5144 | pSMB->Timeout = 0; | ||
5145 | pSMB->Reserved2 = 0; | ||
5146 | param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4; | ||
5147 | offset = param_offset + params; | ||
5148 | |||
5149 | data_offset = (FILE_UNIX_BASIC_INFO *) | ||
5150 | ((char *)(&pSMB->hdr.Protocol) + offset); | ||
5151 | count = sizeof(FILE_UNIX_BASIC_INFO); | ||
5152 | |||
5153 | pSMB->MaxParameterCount = cpu_to_le16(2); | ||
5154 | /* BB find max SMB PDU from sess */ | ||
5155 | pSMB->MaxDataCount = cpu_to_le16(1000); | ||
5156 | pSMB->SetupCount = 1; | ||
5157 | pSMB->Reserved3 = 0; | ||
5158 | pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION); | ||
5159 | byte_count = 3 /* pad */ + params + count; | ||
5160 | pSMB->DataCount = cpu_to_le16(count); | ||
5161 | pSMB->ParameterCount = cpu_to_le16(params); | ||
5162 | pSMB->TotalDataCount = pSMB->DataCount; | ||
5163 | pSMB->TotalParameterCount = pSMB->ParameterCount; | ||
5164 | pSMB->ParameterOffset = cpu_to_le16(param_offset); | ||
5165 | pSMB->DataOffset = cpu_to_le16(offset); | ||
5166 | pSMB->Fid = fid; | ||
5167 | pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC); | ||
5168 | pSMB->Reserved4 = 0; | ||
5169 | pSMB->hdr.smb_buf_length += byte_count; | ||
5170 | pSMB->ByteCount = cpu_to_le16(byte_count); | ||
5171 | |||
5172 | cifs_fill_unix_set_info(data_offset, args); | ||
5173 | |||
5174 | rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0); | ||
5175 | if (rc) | ||
5176 | cFYI(1, ("Send error in Set Time (SetFileInfo) = %d", rc)); | ||
5177 | |||
5178 | /* Note: On -EAGAIN error only caller can retry on handle based calls | ||
5179 | since file handle passed in no longer valid */ | ||
5180 | |||
5181 | return rc; | ||
5182 | } | ||
5183 | |||
5184 | int | ||
5185 | CIFSSMBUnixSetPathInfo(const int xid, struct cifsTconInfo *tcon, char *fileName, | ||
5186 | const struct cifs_unix_set_info_args *args, | ||
5187 | const struct nls_table *nls_codepage, int remap) | ||
5082 | { | 5188 | { |
5083 | TRANSACTION2_SPI_REQ *pSMB = NULL; | 5189 | TRANSACTION2_SPI_REQ *pSMB = NULL; |
5084 | TRANSACTION2_SPI_RSP *pSMBr = NULL; | 5190 | TRANSACTION2_SPI_RSP *pSMBr = NULL; |
@@ -5087,7 +5193,6 @@ CIFSSMBUnixSetInfo(const int xid, struct cifsTconInfo *tcon, char *fileName, | |||
5087 | int bytes_returned = 0; | 5193 | int bytes_returned = 0; |
5088 | FILE_UNIX_BASIC_INFO *data_offset; | 5194 | FILE_UNIX_BASIC_INFO *data_offset; |
5089 | __u16 params, param_offset, offset, count, byte_count; | 5195 | __u16 params, param_offset, offset, count, byte_count; |
5090 | __u64 mode = args->mode; | ||
5091 | 5196 | ||
5092 | cFYI(1, ("In SetUID/GID/Mode")); | 5197 | cFYI(1, ("In SetUID/GID/Mode")); |
5093 | setPermsRetry: | 5198 | setPermsRetry: |
@@ -5138,38 +5243,8 @@ setPermsRetry: | |||
5138 | pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC); | 5243 | pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC); |
5139 | pSMB->Reserved4 = 0; | 5244 | pSMB->Reserved4 = 0; |
5140 | pSMB->hdr.smb_buf_length += byte_count; | 5245 | pSMB->hdr.smb_buf_length += byte_count; |
5141 | /* Samba server ignores set of file size to zero due to bugs in some | ||
5142 | older clients, but we should be precise - we use SetFileSize to | ||
5143 | set file size and do not want to truncate file size to zero | ||
5144 | accidently as happened on one Samba server beta by putting | ||
5145 | zero instead of -1 here */ | ||
5146 | data_offset->EndOfFile = cpu_to_le64(NO_CHANGE_64); | ||
5147 | data_offset->NumOfBytes = cpu_to_le64(NO_CHANGE_64); | ||
5148 | data_offset->LastStatusChange = cpu_to_le64(args->ctime); | ||
5149 | data_offset->LastAccessTime = cpu_to_le64(args->atime); | ||
5150 | data_offset->LastModificationTime = cpu_to_le64(args->mtime); | ||
5151 | data_offset->Uid = cpu_to_le64(args->uid); | ||
5152 | data_offset->Gid = cpu_to_le64(args->gid); | ||
5153 | /* better to leave device as zero when it is */ | ||
5154 | data_offset->DevMajor = cpu_to_le64(MAJOR(args->device)); | ||
5155 | data_offset->DevMinor = cpu_to_le64(MINOR(args->device)); | ||
5156 | data_offset->Permissions = cpu_to_le64(mode); | ||
5157 | |||
5158 | if (S_ISREG(mode)) | ||
5159 | data_offset->Type = cpu_to_le32(UNIX_FILE); | ||
5160 | else if (S_ISDIR(mode)) | ||
5161 | data_offset->Type = cpu_to_le32(UNIX_DIR); | ||
5162 | else if (S_ISLNK(mode)) | ||
5163 | data_offset->Type = cpu_to_le32(UNIX_SYMLINK); | ||
5164 | else if (S_ISCHR(mode)) | ||
5165 | data_offset->Type = cpu_to_le32(UNIX_CHARDEV); | ||
5166 | else if (S_ISBLK(mode)) | ||
5167 | data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV); | ||
5168 | else if (S_ISFIFO(mode)) | ||
5169 | data_offset->Type = cpu_to_le32(UNIX_FIFO); | ||
5170 | else if (S_ISSOCK(mode)) | ||
5171 | data_offset->Type = cpu_to_le32(UNIX_SOCKET); | ||
5172 | 5246 | ||
5247 | cifs_fill_unix_set_info(data_offset, args); | ||
5173 | 5248 | ||
5174 | pSMB->ByteCount = cpu_to_le16(byte_count); | 5249 | pSMB->ByteCount = cpu_to_le16(byte_count); |
5175 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 5250 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |