diff options
Diffstat (limited to 'fs/cifs/cifssmb.c')
-rw-r--r-- | fs/cifs/cifssmb.c | 143 |
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 | ||
5077 | static void | ||
5078 | cifs_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 | |||
5077 | int | 5118 | int |
5078 | CIFSSMBUnixSetInfo(const int xid, struct cifsTconInfo *tcon, char *fileName, | 5119 | CIFSSMBUnixSetFileInfo(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 | |||
5181 | int | ||
5182 | CIFSSMBUnixSetPathInfo(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")); |
5092 | setPermsRetry: | 5195 | setPermsRetry: |
@@ -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, |