aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/cifssmb.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/cifs/cifssmb.c')
-rw-r--r--fs/cifs/cifssmb.c143
1 files changed, 108 insertions, 35 deletions
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 61007c627497..922f5fe2084c 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -5074,10 +5074,114 @@ SetAttrLgcyRetry:
5074} 5074}
5075#endif /* temporarily unneeded SetAttr legacy function */ 5075#endif /* temporarily unneeded SetAttr legacy function */
5076 5076
5077static void
5078cifs_fill_unix_set_info(FILE_UNIX_BASIC_INFO *data_offset,
5079 const struct cifs_unix_set_info_args *args)
5080{
5081 u64 mode = args->mode;
5082
5083 /*
5084 * Samba server ignores set of file size to zero due to bugs in some
5085 * older clients, but we should be precise - we use SetFileSize to
5086 * set file size and do not want to truncate file size to zero
5087 * accidently as happened on one Samba server beta by putting
5088 * zero instead of -1 here
5089 */
5090 data_offset->EndOfFile = cpu_to_le64(NO_CHANGE_64);
5091 data_offset->NumOfBytes = cpu_to_le64(NO_CHANGE_64);
5092 data_offset->LastStatusChange = cpu_to_le64(args->ctime);
5093 data_offset->LastAccessTime = cpu_to_le64(args->atime);
5094 data_offset->LastModificationTime = cpu_to_le64(args->mtime);
5095 data_offset->Uid = cpu_to_le64(args->uid);
5096 data_offset->Gid = cpu_to_le64(args->gid);
5097 /* better to leave device as zero when it is */
5098 data_offset->DevMajor = cpu_to_le64(MAJOR(args->device));
5099 data_offset->DevMinor = cpu_to_le64(MINOR(args->device));
5100 data_offset->Permissions = cpu_to_le64(mode);
5101
5102 if (S_ISREG(mode))
5103 data_offset->Type = cpu_to_le32(UNIX_FILE);
5104 else if (S_ISDIR(mode))
5105 data_offset->Type = cpu_to_le32(UNIX_DIR);
5106 else if (S_ISLNK(mode))
5107 data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
5108 else if (S_ISCHR(mode))
5109 data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
5110 else if (S_ISBLK(mode))
5111 data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
5112 else if (S_ISFIFO(mode))
5113 data_offset->Type = cpu_to_le32(UNIX_FIFO);
5114 else if (S_ISSOCK(mode))
5115 data_offset->Type = cpu_to_le32(UNIX_SOCKET);
5116}
5117
5077int 5118int
5078CIFSSMBUnixSetInfo(const int xid, struct cifsTconInfo *tcon, char *fileName, 5119CIFSSMBUnixSetFileInfo(const int xid, struct cifsTconInfo *tcon,
5079 const struct cifs_unix_set_info_args *args, 5120 const struct cifs_unix_set_info_args *args,
5080 const struct nls_table *nls_codepage, int remap) 5121 u16 fid, u32 pid_of_opener)
5122{
5123 struct smb_com_transaction2_sfi_req *pSMB = NULL;
5124 FILE_UNIX_BASIC_INFO *data_offset;
5125 int rc = 0;
5126 u16 params, param_offset, offset, byte_count, count;
5127
5128 cFYI(1, ("Set Unix Info (via SetFileInfo)"));
5129 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
5130
5131 if (rc)
5132 return rc;
5133
5134 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
5135 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
5136
5137 params = 6;
5138 pSMB->MaxSetupCount = 0;
5139 pSMB->Reserved = 0;
5140 pSMB->Flags = 0;
5141 pSMB->Timeout = 0;
5142 pSMB->Reserved2 = 0;
5143 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
5144 offset = param_offset + params;
5145
5146 data_offset = (FILE_UNIX_BASIC_INFO *)
5147 ((char *)(&pSMB->hdr.Protocol) + offset);
5148 count = sizeof(FILE_UNIX_BASIC_INFO);
5149
5150 pSMB->MaxParameterCount = cpu_to_le16(2);
5151 /* BB find max SMB PDU from sess */
5152 pSMB->MaxDataCount = cpu_to_le16(1000);
5153 pSMB->SetupCount = 1;
5154 pSMB->Reserved3 = 0;
5155 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
5156 byte_count = 3 /* pad */ + params + count;
5157 pSMB->DataCount = cpu_to_le16(count);
5158 pSMB->ParameterCount = cpu_to_le16(params);
5159 pSMB->TotalDataCount = pSMB->DataCount;
5160 pSMB->TotalParameterCount = pSMB->ParameterCount;
5161 pSMB->ParameterOffset = cpu_to_le16(param_offset);
5162 pSMB->DataOffset = cpu_to_le16(offset);
5163 pSMB->Fid = fid;
5164 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
5165 pSMB->Reserved4 = 0;
5166 pSMB->hdr.smb_buf_length += byte_count;
5167 pSMB->ByteCount = cpu_to_le16(byte_count);
5168
5169 cifs_fill_unix_set_info(data_offset, args);
5170
5171 rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
5172 if (rc)
5173 cFYI(1, ("Send error in Set Time (SetFileInfo) = %d", rc));
5174
5175 /* Note: On -EAGAIN error only caller can retry on handle based calls
5176 since file handle passed in no longer valid */
5177
5178 return rc;
5179}
5180
5181int
5182CIFSSMBUnixSetPathInfo(const int xid, struct cifsTconInfo *tcon, char *fileName,
5183 const struct cifs_unix_set_info_args *args,
5184 const struct nls_table *nls_codepage, int remap)
5081{ 5185{
5082 TRANSACTION2_SPI_REQ *pSMB = NULL; 5186 TRANSACTION2_SPI_REQ *pSMB = NULL;
5083 TRANSACTION2_SPI_RSP *pSMBr = NULL; 5187 TRANSACTION2_SPI_RSP *pSMBr = NULL;
@@ -5086,7 +5190,6 @@ CIFSSMBUnixSetInfo(const int xid, struct cifsTconInfo *tcon, char *fileName,
5086 int bytes_returned = 0; 5190 int bytes_returned = 0;
5087 FILE_UNIX_BASIC_INFO *data_offset; 5191 FILE_UNIX_BASIC_INFO *data_offset;
5088 __u16 params, param_offset, offset, count, byte_count; 5192 __u16 params, param_offset, offset, count, byte_count;
5089 __u64 mode = args->mode;
5090 5193
5091 cFYI(1, ("In SetUID/GID/Mode")); 5194 cFYI(1, ("In SetUID/GID/Mode"));
5092setPermsRetry: 5195setPermsRetry:
@@ -5137,38 +5240,8 @@ setPermsRetry:
5137 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC); 5240 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
5138 pSMB->Reserved4 = 0; 5241 pSMB->Reserved4 = 0;
5139 pSMB->hdr.smb_buf_length += byte_count; 5242 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 5243
5244 cifs_fill_unix_set_info(data_offset, args);
5172 5245
5173 pSMB->ByteCount = cpu_to_le16(byte_count); 5246 pSMB->ByteCount = cpu_to_le16(byte_count);
5174 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, 5247 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,