diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/cifs/cifsproto.h | 2 | ||||
-rw-r--r-- | fs/cifs/cifssmb.c | 55 | ||||
-rw-r--r-- | fs/cifs/inode.c | 9 |
3 files changed, 64 insertions, 2 deletions
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index a729d083e6f..014f26c7864 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -179,6 +179,8 @@ extern int CIFSSMBSetPathInfo(const int xid, struct cifsTconInfo *tcon, extern int CIFSSMBSetFileInfo(const int xid, struct cifsTconInfo *tcon, const FILE_BASIC_INFO *data, __u16 fid, __u32 pid_of_opener); +extern int CIFSSMBSetFileDisposition(const int xid, struct cifsTconInfo *tcon, + bool delete_file, __u16 fid, __u32 pid_of_opener); #if 0 extern int CIFSSMBSetAttrLegacy(int xid, struct cifsTconInfo *tcon, char *fileName, __u16 dos_attributes, diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 994de7c9047..7b365842bfa 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -4876,6 +4876,61 @@ CIFSSMBSetFileInfo(const int xid, struct cifsTconInfo *tcon, return rc; } +int +CIFSSMBSetFileDisposition(const int xid, struct cifsTconInfo *tcon, + bool delete_file, __u16 fid, __u32 pid_of_opener) +{ + struct smb_com_transaction2_sfi_req *pSMB = NULL; + char *data_offset; + int rc = 0; + __u16 params, param_offset, offset, byte_count, count; + + cFYI(1, ("Set File Disposition (via SetFileInfo)")); + rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB); + + if (rc) + return rc; + + pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener); + pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16)); + + params = 6; + pSMB->MaxSetupCount = 0; + pSMB->Reserved = 0; + pSMB->Flags = 0; + pSMB->Timeout = 0; + pSMB->Reserved2 = 0; + param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4; + offset = param_offset + params; + + data_offset = (char *) (&pSMB->hdr.Protocol) + offset; + + count = 1; + pSMB->MaxParameterCount = cpu_to_le16(2); + /* BB find max SMB PDU from sess */ + pSMB->MaxDataCount = cpu_to_le16(1000); + pSMB->SetupCount = 1; + pSMB->Reserved3 = 0; + pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION); + byte_count = 3 /* pad */ + params + count; + pSMB->DataCount = cpu_to_le16(count); + pSMB->ParameterCount = cpu_to_le16(params); + pSMB->TotalDataCount = pSMB->DataCount; + pSMB->TotalParameterCount = pSMB->ParameterCount; + pSMB->ParameterOffset = cpu_to_le16(param_offset); + pSMB->DataOffset = cpu_to_le16(offset); + pSMB->Fid = fid; + pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_DISPOSITION_INFO); + pSMB->Reserved4 = 0; + pSMB->hdr.smb_buf_length += byte_count; + pSMB->ByteCount = cpu_to_le16(byte_count); + *data_offset = delete_file ? 1 : 0; + rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0); + if (rc) + cFYI(1, ("Send error in SetFileDisposition = %d", rc)); + + return rc; +} int CIFSSMBSetPathInfo(const int xid, struct cifsTconInfo *tcon, diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 660aac81160..954b670f168 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -778,8 +778,7 @@ cifs_rename_pending_delete(char *full_path, struct inode *inode, int xid) FILE_BASIC_INFO *info_buf; rc = CIFSSMBOpen(xid, tcon, full_path, FILE_OPEN, - DELETE|FILE_WRITE_ATTRIBUTES, - CREATE_NOT_DIR|CREATE_DELETE_ON_CLOSE, + DELETE|FILE_WRITE_ATTRIBUTES, CREATE_NOT_DIR, &netfid, &oplock, NULL, cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); if (rc != 0) @@ -807,6 +806,12 @@ cifs_rename_pending_delete(char *full_path, struct inode *inode, int xid) rc = CIFSSMBRenameOpenFile(xid, tcon, netfid, NULL, cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); + if (rc != 0) + goto out_close; + + /* set DELETE_ON_CLOSE */ + rc = CIFSSMBSetFileDisposition(xid, tcon, true, netfid, current->tgid); + out_close: CIFSSMBClose(xid, tcon, netfid); out: |