Commit af337a9c authored by Steve French's avatar Steve French Committed by Steve French

Fix rename open file to better match standard unix semantics

parent 707c5db2
...@@ -958,6 +958,7 @@ typedef union smb_com_transaction2 { ...@@ -958,6 +958,7 @@ typedef union smb_com_transaction2 {
#define SMB_SET_FILE_UNIX_LINK 0x201 #define SMB_SET_FILE_UNIX_LINK 0x201
#define SMB_SET_FILE_UNIX_HLINK 0x203 #define SMB_SET_FILE_UNIX_HLINK 0x203
#define SMB_SET_FILE_BASIC_INFO2 0x3ec #define SMB_SET_FILE_BASIC_INFO2 0x3ec
#define SMB_SET_FILE_RENAME_INFORMATION 0x3f2
#define SMB_SET_FILE_ALLOCATION_INFO2 0x3fb #define SMB_SET_FILE_ALLOCATION_INFO2 0x3fb
#define SMB_SET_FILE_END_OF_FILE_INFO2 0x3fc #define SMB_SET_FILE_END_OF_FILE_INFO2 0x3fc
...@@ -1053,6 +1054,13 @@ typedef struct smb_com_transaction2_spi_rsp { ...@@ -1053,6 +1054,13 @@ typedef struct smb_com_transaction2_spi_rsp {
__u16 Reserved2; /* parameter word reserved - present for infolevels > 100 */ __u16 Reserved2; /* parameter word reserved - present for infolevels > 100 */
} TRANSACTION2_SPI_RSP; } TRANSACTION2_SPI_RSP;
struct set_file_rename {
__u32 overwrite; /* 1 = overwrite dest */
__u32 root_fid; /* zero */
__u32 target_name_len;
char target_name[0]; /* Must be unicode */
};
struct smb_com_transaction2_sfi_req { struct smb_com_transaction2_sfi_req {
struct smb_hdr hdr; /* wct = 15 */ struct smb_hdr hdr; /* wct = 15 */
__u16 TotalParameterCount; __u16 TotalParameterCount;
......
...@@ -170,6 +170,8 @@ extern int CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon, ...@@ -170,6 +170,8 @@ extern int CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon,
extern int CIFSSMBRename(const int xid, struct cifsTconInfo *tcon, extern int CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
const char *fromName, const char *toName, const char *fromName, const char *toName,
const struct nls_table *nls_codepage); const struct nls_table *nls_codepage);
extern int CIFSSMBDummyRenameOpenFile(const int xid,struct cifsTconInfo *pTcon,
int netfid, const struct nls_table *nls_codepage);
extern int CIFSCreateHardLink(const int xid, extern int CIFSCreateHardLink(const int xid,
struct cifsTconInfo *tcon, struct cifsTconInfo *tcon,
const char *fromName, const char *toName, const char *fromName, const char *toName,
......
...@@ -762,6 +762,72 @@ CIFSSMBRename(const int xid, struct cifsTconInfo *tcon, ...@@ -762,6 +762,72 @@ CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
return rc; return rc;
} }
int CIFSSMBDummyRenameOpenFile(const int xid,struct cifsTconInfo *pTcon,
int netfid, const struct nls_table * nls_codepage)
{
struct smb_com_transaction2_sfi_req *pSMB = NULL;
struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
struct set_file_rename * rename_info;
char *data_offset;
int rc = 0;
int bytes_returned = 0;
int len_of_str;
cFYI(1, ("Rename to Dummy Random File Name"));
rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
(void **) &pSMBr);
if (rc)
return rc;
pSMB->ParameterCount = 6;
pSMB->MaxSetupCount = 0;
pSMB->Reserved = 0;
pSMB->Flags = 0;
pSMB->Timeout = 0;
pSMB->Reserved2 = 0;
pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_sfi_req,
Fid) - 4;
pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
data_offset = (char *) (&pSMB->hdr.Protocol) + pSMB->DataOffset;
rename_info = (struct set_file_rename *) data_offset;
pSMB->MaxParameterCount = cpu_to_le16(2);
pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
pSMB->SetupCount = 1;
pSMB->Reserved3 = 0;
pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
pSMB->ByteCount = 3 /* pad */ + pSMB->ParameterCount;
pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
pSMB->TotalParameterCount = pSMB->ParameterCount;
pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
/* construct random name ".cifs_tmp<inodenum><mid>" */
rename_info->overwrite = cpu_to_le32(1);
rename_info->root_fid = 0;
len_of_str = cifs_strtoUCS((wchar_t *) rename_info->target_name, ".cifs", 12, nls_codepage);
pSMB->DataCount = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str);
pSMB->ByteCount += pSMB->DataCount;
pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
pSMB->Fid = netfid;
/* should we check the passthrough bit ? */
pSMB->InformationLevel =
cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
pSMB->Reserved4 = 0;
pSMB->hdr.smb_buf_length += pSMB->ByteCount;
pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
if (rc) {
cFYI(1,("Send error in DummyRename = %d", rc));
}
if (pSMB)
buf_release(pSMB);
return rc;
}
int int
CIFSUnixCreateSymLink(const int xid, struct cifsTconInfo *tcon, CIFSUnixCreateSymLink(const int xid, struct cifsTconInfo *tcon,
const char *fromName, const char *toName, const char *fromName, const char *toName,
...@@ -1979,7 +2045,7 @@ CIFSSMBQFSDeviceInfo(int xid, struct cifsTconInfo *tcon, ...@@ -1979,7 +2045,7 @@ CIFSSMBQFSDeviceInfo(int xid, struct cifsTconInfo *tcon,
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
(struct smb_hdr *) pSMBr, &bytes_returned, 0); (struct smb_hdr *) pSMBr, &bytes_returned, 0);
if (rc) { if (rc) {
cERROR(1, ("Send error in QFSDeviceInfo = %d", rc)); cFYI(1, ("Send error in QFSDeviceInfo = %d", rc));
} else { /* decode response */ } else { /* decode response */
pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset); pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
if ((pSMBr->ByteCount < sizeof (FILE_SYSTEM_DEVICE_INFO)) if ((pSMBr->ByteCount < sizeof (FILE_SYSTEM_DEVICE_INFO))
...@@ -2202,10 +2268,10 @@ CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size, ...@@ -2202,10 +2268,10 @@ CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
pSMB->TotalDataCount = pSMB->DataCount; pSMB->TotalDataCount = pSMB->DataCount;
pSMB->TotalParameterCount = pSMB->ParameterCount; pSMB->TotalParameterCount = pSMB->ParameterCount;
pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset); pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
parm_data = parm_data =
(struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) + (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
pSMB->DataOffset); pSMB->DataOffset);
pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset); /* now safe to change to le */
parm_data->FileSize = size; parm_data->FileSize = size;
pSMB->Fid = fid; pSMB->Fid = fid;
if(SetAllocation) { if(SetAllocation) {
......
...@@ -353,8 +353,9 @@ cifs_unlink(struct inode *inode, struct dentry *direntry) ...@@ -353,8 +353,9 @@ cifs_unlink(struct inode *inode, struct dentry *direntry)
CREATE_NOT_DIR | CREATE_DELETE_ON_CLOSE, CREATE_NOT_DIR | CREATE_DELETE_ON_CLOSE,
&netfid, &oplock, NULL, cifs_sb->local_nls); &netfid, &oplock, NULL, cifs_sb->local_nls);
if(rc==0) { if(rc==0) {
CIFSSMBDummyRenameOpenFile(xid,pTcon,netfid,
cifs_sb->local_nls);
CIFSSMBClose(xid, pTcon, netfid); CIFSSMBClose(xid, pTcon, netfid);
/* BB In the future chain close with the NTCreateX to narrow window */
direntry->d_inode->i_nlink--; direntry->d_inode->i_nlink--;
} }
} else if (rc == -EACCES) { } else if (rc == -EACCES) {
...@@ -370,8 +371,22 @@ cifs_unlink(struct inode *inode, struct dentry *direntry) ...@@ -370,8 +371,22 @@ cifs_unlink(struct inode *inode, struct dentry *direntry)
} }
if(rc==0) { if(rc==0) {
rc = CIFSSMBDelFile(xid, pTcon, full_path, cifs_sb->local_nls); rc = CIFSSMBDelFile(xid, pTcon, full_path, cifs_sb->local_nls);
if (!rc) if (!rc) {
direntry->d_inode->i_nlink--; direntry->d_inode->i_nlink--;
} else if (rc == -ETXTBSY) {
int oplock = FALSE;
__u16 netfid;
rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, DELETE,
CREATE_NOT_DIR | CREATE_DELETE_ON_CLOSE,
&netfid, &oplock, NULL, cifs_sb->local_nls);
if(rc==0) {
CIFSSMBDummyRenameOpenFile(xid,pTcon,netfid,cifs_sb->local_nls);
CIFSSMBClose(xid, pTcon, netfid);
direntry->d_inode->i_nlink--;
}
/* BB if rc = -ETXTBUSY goto the rename logic BB */
}
} }
} }
cifsInode = CIFS_I(direntry->d_inode); cifsInode = CIFS_I(direntry->d_inode);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment