diff options
Diffstat (limited to 'fs/cifs/cifssmb.c')
-rw-r--r-- | fs/cifs/cifssmb.c | 148 |
1 files changed, 112 insertions, 36 deletions
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 61007c627497..1866bc2927d4 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c | |||
@@ -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; |
@@ -5074,10 +5077,114 @@ SetAttrLgcyRetry: | |||
5074 | } | 5077 | } |
5075 | #endif /* temporarily unneeded SetAttr legacy function */ | 5078 | #endif /* temporarily unneeded SetAttr legacy function */ |
5076 | 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 | |||
5077 | int | 5121 | int |
5078 | CIFSSMBUnixSetInfo(const int xid, struct cifsTconInfo *tcon, char *fileName, | 5122 | CIFSSMBUnixSetFileInfo(const int xid, struct cifsTconInfo *tcon, |
5079 | const struct cifs_unix_set_info_args *args, | 5123 | const struct cifs_unix_set_info_args *args, |
5080 | 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) | ||
5081 | { | 5188 | { |
5082 | TRANSACTION2_SPI_REQ *pSMB = NULL; | 5189 | TRANSACTION2_SPI_REQ *pSMB = NULL; |
5083 | TRANSACTION2_SPI_RSP *pSMBr = NULL; | 5190 | TRANSACTION2_SPI_RSP *pSMBr = NULL; |
@@ -5086,7 +5193,6 @@ CIFSSMBUnixSetInfo(const int xid, struct cifsTconInfo *tcon, char *fileName, | |||
5086 | int bytes_returned = 0; | 5193 | int bytes_returned = 0; |
5087 | FILE_UNIX_BASIC_INFO *data_offset; | 5194 | FILE_UNIX_BASIC_INFO *data_offset; |
5088 | __u16 params, param_offset, offset, count, byte_count; | 5195 | __u16 params, param_offset, offset, count, byte_count; |
5089 | __u64 mode = args->mode; | ||
5090 | 5196 | ||
5091 | cFYI(1, ("In SetUID/GID/Mode")); | 5197 | cFYI(1, ("In SetUID/GID/Mode")); |
5092 | setPermsRetry: | 5198 | setPermsRetry: |
@@ -5137,38 +5243,8 @@ setPermsRetry: | |||
5137 | pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC); | 5243 | pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC); |
5138 | pSMB->Reserved4 = 0; | 5244 | pSMB->Reserved4 = 0; |
5139 | pSMB->hdr.smb_buf_length += byte_count; | 5245 | pSMB->hdr.smb_buf_length += byte_count; |
5140 | /* Samba server ignores set of file size to zero due to bugs in some | ||
5141 | older clients, but we should be precise - we use SetFileSize to | ||
5142 | set file size and do not want to truncate file size to zero | ||
5143 | accidently as happened on one Samba server beta by putting | ||
5144 | zero instead of -1 here */ | ||
5145 | data_offset->EndOfFile = cpu_to_le64(NO_CHANGE_64); | ||
5146 | data_offset->NumOfBytes = cpu_to_le64(NO_CHANGE_64); | ||
5147 | data_offset->LastStatusChange = cpu_to_le64(args->ctime); | ||
5148 | data_offset->LastAccessTime = cpu_to_le64(args->atime); | ||
5149 | data_offset->LastModificationTime = cpu_to_le64(args->mtime); | ||
5150 | data_offset->Uid = cpu_to_le64(args->uid); | ||
5151 | data_offset->Gid = cpu_to_le64(args->gid); | ||
5152 | /* better to leave device as zero when it is */ | ||
5153 | data_offset->DevMajor = cpu_to_le64(MAJOR(args->device)); | ||
5154 | data_offset->DevMinor = cpu_to_le64(MINOR(args->device)); | ||
5155 | data_offset->Permissions = cpu_to_le64(mode); | ||
5156 | |||
5157 | if (S_ISREG(mode)) | ||
5158 | data_offset->Type = cpu_to_le32(UNIX_FILE); | ||
5159 | else if (S_ISDIR(mode)) | ||
5160 | data_offset->Type = cpu_to_le32(UNIX_DIR); | ||
5161 | else if (S_ISLNK(mode)) | ||
5162 | data_offset->Type = cpu_to_le32(UNIX_SYMLINK); | ||
5163 | else if (S_ISCHR(mode)) | ||
5164 | data_offset->Type = cpu_to_le32(UNIX_CHARDEV); | ||
5165 | else if (S_ISBLK(mode)) | ||
5166 | data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV); | ||
5167 | else if (S_ISFIFO(mode)) | ||
5168 | data_offset->Type = cpu_to_le32(UNIX_FIFO); | ||
5169 | else if (S_ISSOCK(mode)) | ||
5170 | data_offset->Type = cpu_to_le32(UNIX_SOCKET); | ||
5171 | 5246 | ||
5247 | cifs_fill_unix_set_info(data_offset, args); | ||
5172 | 5248 | ||
5173 | pSMB->ByteCount = cpu_to_le16(byte_count); | 5249 | pSMB->ByteCount = cpu_to_le16(byte_count); |
5174 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 5250 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |