CIFS: Move rename to ops struct
Signed-off-by: Pavel Shilovsky <pshilovsky@samba.org> Signed-off-by: Steve French <smfrench@gmail.com>
This commit is contained in:
parent
3c1bf7e48e
commit
8ceb984379
|
@ -275,6 +275,9 @@ struct smb_version_operations {
|
||||||
/* open, rename and delete file */
|
/* open, rename and delete file */
|
||||||
int (*rename_pending_delete)(const char *, struct dentry *,
|
int (*rename_pending_delete)(const char *, struct dentry *,
|
||||||
const unsigned int);
|
const unsigned int);
|
||||||
|
/* send rename request */
|
||||||
|
int (*rename)(const unsigned int, struct cifs_tcon *, const char *,
|
||||||
|
const char *, struct cifs_sb_info *);
|
||||||
/* open a file for non-posix mounts */
|
/* open a file for non-posix mounts */
|
||||||
int (*open)(const unsigned int, struct cifs_tcon *, const char *, int,
|
int (*open)(const unsigned int, struct cifs_tcon *, const char *, int,
|
||||||
int, int, struct cifs_fid *, __u32 *, FILE_ALL_INFO *,
|
int, int, struct cifs_fid *, __u32 *, FILE_ALL_INFO *,
|
||||||
|
|
|
@ -310,9 +310,8 @@ extern int CIFSPOSIXDelFile(const unsigned int xid, struct cifs_tcon *tcon,
|
||||||
extern int CIFSSMBDelFile(const unsigned int xid, struct cifs_tcon *tcon,
|
extern int CIFSSMBDelFile(const unsigned int xid, struct cifs_tcon *tcon,
|
||||||
const char *name, struct cifs_sb_info *cifs_sb);
|
const char *name, struct cifs_sb_info *cifs_sb);
|
||||||
extern int CIFSSMBRename(const unsigned int xid, struct cifs_tcon *tcon,
|
extern int CIFSSMBRename(const unsigned int xid, struct cifs_tcon *tcon,
|
||||||
const char *fromName, const char *toName,
|
const char *from_name, const char *to_name,
|
||||||
const struct nls_table *nls_codepage,
|
struct cifs_sb_info *cifs_sb);
|
||||||
int remap_special_chars);
|
|
||||||
extern int CIFSSMBRenameOpenFile(const unsigned int xid, struct cifs_tcon *tcon,
|
extern int CIFSSMBRenameOpenFile(const unsigned int xid, struct cifs_tcon *tcon,
|
||||||
int netfid, const char *target_name,
|
int netfid, const char *target_name,
|
||||||
const struct nls_table *nls_codepage,
|
const struct nls_table *nls_codepage,
|
||||||
|
|
|
@ -2531,8 +2531,8 @@ CIFSSMBFlush(const unsigned int xid, struct cifs_tcon *tcon, int smb_file_id)
|
||||||
|
|
||||||
int
|
int
|
||||||
CIFSSMBRename(const unsigned int xid, struct cifs_tcon *tcon,
|
CIFSSMBRename(const unsigned int xid, struct cifs_tcon *tcon,
|
||||||
const char *fromName, const char *toName,
|
const char *from_name, const char *to_name,
|
||||||
const struct nls_table *nls_codepage, int remap)
|
struct cifs_sb_info *cifs_sb)
|
||||||
{
|
{
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
RENAME_REQ *pSMB = NULL;
|
RENAME_REQ *pSMB = NULL;
|
||||||
|
@ -2540,6 +2540,7 @@ CIFSSMBRename(const unsigned int xid, struct cifs_tcon *tcon,
|
||||||
int bytes_returned;
|
int bytes_returned;
|
||||||
int name_len, name_len2;
|
int name_len, name_len2;
|
||||||
__u16 count;
|
__u16 count;
|
||||||
|
int remap = cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR;
|
||||||
|
|
||||||
cFYI(1, "In CIFSSMBRename");
|
cFYI(1, "In CIFSSMBRename");
|
||||||
renameRetry:
|
renameRetry:
|
||||||
|
@ -2554,9 +2555,9 @@ renameRetry:
|
||||||
ATTR_DIRECTORY);
|
ATTR_DIRECTORY);
|
||||||
|
|
||||||
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
|
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
|
||||||
name_len =
|
name_len = cifsConvertToUTF16((__le16 *) pSMB->OldFileName,
|
||||||
cifsConvertToUTF16((__le16 *) pSMB->OldFileName, fromName,
|
from_name, PATH_MAX,
|
||||||
PATH_MAX, nls_codepage, remap);
|
cifs_sb->local_nls, remap);
|
||||||
name_len++; /* trailing null */
|
name_len++; /* trailing null */
|
||||||
name_len *= 2;
|
name_len *= 2;
|
||||||
pSMB->OldFileName[name_len] = 0x04; /* pad */
|
pSMB->OldFileName[name_len] = 0x04; /* pad */
|
||||||
|
@ -2564,17 +2565,18 @@ renameRetry:
|
||||||
pSMB->OldFileName[name_len + 1] = 0x00;
|
pSMB->OldFileName[name_len + 1] = 0x00;
|
||||||
name_len2 =
|
name_len2 =
|
||||||
cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
|
cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
|
||||||
toName, PATH_MAX, nls_codepage, remap);
|
to_name, PATH_MAX, cifs_sb->local_nls,
|
||||||
|
remap);
|
||||||
name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
|
name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
|
||||||
name_len2 *= 2; /* convert to bytes */
|
name_len2 *= 2; /* convert to bytes */
|
||||||
} else { /* BB improve the check for buffer overruns BB */
|
} else { /* BB improve the check for buffer overruns BB */
|
||||||
name_len = strnlen(fromName, PATH_MAX);
|
name_len = strnlen(from_name, PATH_MAX);
|
||||||
name_len++; /* trailing null */
|
name_len++; /* trailing null */
|
||||||
strncpy(pSMB->OldFileName, fromName, name_len);
|
strncpy(pSMB->OldFileName, from_name, name_len);
|
||||||
name_len2 = strnlen(toName, PATH_MAX);
|
name_len2 = strnlen(to_name, PATH_MAX);
|
||||||
name_len2++; /* trailing null */
|
name_len2++; /* trailing null */
|
||||||
pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
|
pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
|
||||||
strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
|
strncpy(&pSMB->OldFileName[name_len + 1], to_name, name_len2);
|
||||||
name_len2++; /* trailing null */
|
name_len2++; /* trailing null */
|
||||||
name_len2++; /* signature byte */
|
name_len2++; /* signature byte */
|
||||||
}
|
}
|
||||||
|
|
|
@ -1512,29 +1512,32 @@ rmdir_exit:
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
cifs_do_rename(unsigned int xid, struct dentry *from_dentry,
|
cifs_do_rename(const unsigned int xid, struct dentry *from_dentry,
|
||||||
const char *fromPath, struct dentry *to_dentry,
|
const char *from_path, struct dentry *to_dentry,
|
||||||
const char *toPath)
|
const char *to_path)
|
||||||
{
|
{
|
||||||
struct cifs_sb_info *cifs_sb = CIFS_SB(from_dentry->d_sb);
|
struct cifs_sb_info *cifs_sb = CIFS_SB(from_dentry->d_sb);
|
||||||
struct tcon_link *tlink;
|
struct tcon_link *tlink;
|
||||||
struct cifs_tcon *pTcon;
|
struct cifs_tcon *tcon;
|
||||||
|
struct TCP_Server_Info *server;
|
||||||
__u16 srcfid;
|
__u16 srcfid;
|
||||||
int oplock, rc;
|
int oplock, rc;
|
||||||
|
|
||||||
tlink = cifs_sb_tlink(cifs_sb);
|
tlink = cifs_sb_tlink(cifs_sb);
|
||||||
if (IS_ERR(tlink))
|
if (IS_ERR(tlink))
|
||||||
return PTR_ERR(tlink);
|
return PTR_ERR(tlink);
|
||||||
pTcon = tlink_tcon(tlink);
|
tcon = tlink_tcon(tlink);
|
||||||
|
server = tcon->ses->server;
|
||||||
|
|
||||||
|
if (!server->ops->rename)
|
||||||
|
return -ENOSYS;
|
||||||
|
|
||||||
/* try path-based rename first */
|
/* try path-based rename first */
|
||||||
rc = CIFSSMBRename(xid, pTcon, fromPath, toPath, cifs_sb->local_nls,
|
rc = server->ops->rename(xid, tcon, from_path, to_path, cifs_sb);
|
||||||
cifs_sb->mnt_cifs_flags &
|
|
||||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* don't bother with rename by filehandle unless file is busy and
|
* Don't bother with rename by filehandle unless file is busy and
|
||||||
* source Note that cross directory moves do not work with
|
* source. Note that cross directory moves do not work with
|
||||||
* rename by filehandle to various Windows servers.
|
* rename by filehandle to various Windows servers.
|
||||||
*/
|
*/
|
||||||
if (rc == 0 || rc != -ETXTBSY)
|
if (rc == 0 || rc != -ETXTBSY)
|
||||||
|
@ -1545,29 +1548,28 @@ cifs_do_rename(unsigned int xid, struct dentry *from_dentry,
|
||||||
goto do_rename_exit;
|
goto do_rename_exit;
|
||||||
|
|
||||||
/* open the file to be renamed -- we need DELETE perms */
|
/* open the file to be renamed -- we need DELETE perms */
|
||||||
rc = CIFSSMBOpen(xid, pTcon, fromPath, FILE_OPEN, DELETE,
|
rc = CIFSSMBOpen(xid, tcon, from_path, FILE_OPEN, DELETE,
|
||||||
CREATE_NOT_DIR, &srcfid, &oplock, NULL,
|
CREATE_NOT_DIR, &srcfid, &oplock, NULL,
|
||||||
cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
|
cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
|
||||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||||
|
|
||||||
if (rc == 0) {
|
if (rc == 0) {
|
||||||
rc = CIFSSMBRenameOpenFile(xid, pTcon, srcfid,
|
rc = CIFSSMBRenameOpenFile(xid, tcon, srcfid,
|
||||||
(const char *) to_dentry->d_name.name,
|
(const char *) to_dentry->d_name.name,
|
||||||
cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
|
cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
|
||||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||||
|
CIFSSMBClose(xid, tcon, srcfid);
|
||||||
CIFSSMBClose(xid, pTcon, srcfid);
|
|
||||||
}
|
}
|
||||||
do_rename_exit:
|
do_rename_exit:
|
||||||
cifs_put_tlink(tlink);
|
cifs_put_tlink(tlink);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cifs_rename(struct inode *source_dir, struct dentry *source_dentry,
|
int
|
||||||
struct inode *target_dir, struct dentry *target_dentry)
|
cifs_rename(struct inode *source_dir, struct dentry *source_dentry,
|
||||||
|
struct inode *target_dir, struct dentry *target_dentry)
|
||||||
{
|
{
|
||||||
char *fromName = NULL;
|
char *from_name = NULL;
|
||||||
char *toName = NULL;
|
char *to_name = NULL;
|
||||||
struct cifs_sb_info *cifs_sb;
|
struct cifs_sb_info *cifs_sb;
|
||||||
struct tcon_link *tlink;
|
struct tcon_link *tlink;
|
||||||
struct cifs_tcon *tcon;
|
struct cifs_tcon *tcon;
|
||||||
|
@ -1588,25 +1590,25 @@ int cifs_rename(struct inode *source_dir, struct dentry *source_dentry,
|
||||||
* we already have the rename sem so we do not need to
|
* we already have the rename sem so we do not need to
|
||||||
* grab it again here to protect the path integrity
|
* grab it again here to protect the path integrity
|
||||||
*/
|
*/
|
||||||
fromName = build_path_from_dentry(source_dentry);
|
from_name = build_path_from_dentry(source_dentry);
|
||||||
if (fromName == NULL) {
|
if (from_name == NULL) {
|
||||||
rc = -ENOMEM;
|
rc = -ENOMEM;
|
||||||
goto cifs_rename_exit;
|
goto cifs_rename_exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
toName = build_path_from_dentry(target_dentry);
|
to_name = build_path_from_dentry(target_dentry);
|
||||||
if (toName == NULL) {
|
if (to_name == NULL) {
|
||||||
rc = -ENOMEM;
|
rc = -ENOMEM;
|
||||||
goto cifs_rename_exit;
|
goto cifs_rename_exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = cifs_do_rename(xid, source_dentry, fromName,
|
rc = cifs_do_rename(xid, source_dentry, from_name, target_dentry,
|
||||||
target_dentry, toName);
|
to_name);
|
||||||
|
|
||||||
if (rc == -EEXIST && tcon->unix_ext) {
|
if (rc == -EEXIST && tcon->unix_ext) {
|
||||||
/*
|
/*
|
||||||
* Are src and dst hardlinks of same inode? We can
|
* Are src and dst hardlinks of same inode? We can only tell
|
||||||
* only tell with unix extensions enabled
|
* with unix extensions enabled.
|
||||||
*/
|
*/
|
||||||
info_buf_source =
|
info_buf_source =
|
||||||
kmalloc(2 * sizeof(FILE_UNIX_BASIC_INFO),
|
kmalloc(2 * sizeof(FILE_UNIX_BASIC_INFO),
|
||||||
|
@ -1617,19 +1619,19 @@ int cifs_rename(struct inode *source_dir, struct dentry *source_dentry,
|
||||||
}
|
}
|
||||||
|
|
||||||
info_buf_target = info_buf_source + 1;
|
info_buf_target = info_buf_source + 1;
|
||||||
tmprc = CIFSSMBUnixQPathInfo(xid, tcon, fromName,
|
tmprc = CIFSSMBUnixQPathInfo(xid, tcon, from_name,
|
||||||
info_buf_source,
|
info_buf_source,
|
||||||
cifs_sb->local_nls,
|
cifs_sb->local_nls,
|
||||||
cifs_sb->mnt_cifs_flags &
|
cifs_sb->mnt_cifs_flags &
|
||||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||||
if (tmprc != 0)
|
if (tmprc != 0)
|
||||||
goto unlink_target;
|
goto unlink_target;
|
||||||
|
|
||||||
tmprc = CIFSSMBUnixQPathInfo(xid, tcon, toName,
|
tmprc = CIFSSMBUnixQPathInfo(xid, tcon, to_name,
|
||||||
info_buf_target,
|
info_buf_target,
|
||||||
cifs_sb->local_nls,
|
cifs_sb->local_nls,
|
||||||
cifs_sb->mnt_cifs_flags &
|
cifs_sb->mnt_cifs_flags &
|
||||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||||
|
|
||||||
if (tmprc == 0 && (info_buf_source->UniqueId ==
|
if (tmprc == 0 && (info_buf_source->UniqueId ==
|
||||||
info_buf_target->UniqueId)) {
|
info_buf_target->UniqueId)) {
|
||||||
|
@ -1637,8 +1639,11 @@ int cifs_rename(struct inode *source_dir, struct dentry *source_dentry,
|
||||||
rc = 0;
|
rc = 0;
|
||||||
goto cifs_rename_exit;
|
goto cifs_rename_exit;
|
||||||
}
|
}
|
||||||
} /* else ... BB we could add the same check for Windows by
|
}
|
||||||
checking the UniqueId via FILE_INTERNAL_INFO */
|
/*
|
||||||
|
* else ... BB we could add the same check for Windows by
|
||||||
|
* checking the UniqueId via FILE_INTERNAL_INFO
|
||||||
|
*/
|
||||||
|
|
||||||
unlink_target:
|
unlink_target:
|
||||||
/* Try unlinking the target dentry if it's not negative */
|
/* Try unlinking the target dentry if it's not negative */
|
||||||
|
@ -1646,15 +1651,14 @@ unlink_target:
|
||||||
tmprc = cifs_unlink(target_dir, target_dentry);
|
tmprc = cifs_unlink(target_dir, target_dentry);
|
||||||
if (tmprc)
|
if (tmprc)
|
||||||
goto cifs_rename_exit;
|
goto cifs_rename_exit;
|
||||||
|
rc = cifs_do_rename(xid, source_dentry, from_name,
|
||||||
rc = cifs_do_rename(xid, source_dentry, fromName,
|
target_dentry, to_name);
|
||||||
target_dentry, toName);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cifs_rename_exit:
|
cifs_rename_exit:
|
||||||
kfree(info_buf_source);
|
kfree(info_buf_source);
|
||||||
kfree(fromName);
|
kfree(from_name);
|
||||||
kfree(toName);
|
kfree(to_name);
|
||||||
free_xid(xid);
|
free_xid(xid);
|
||||||
cifs_put_tlink(tlink);
|
cifs_put_tlink(tlink);
|
||||||
return rc;
|
return rc;
|
||||||
|
|
|
@ -800,6 +800,7 @@ struct smb_version_operations smb1_operations = {
|
||||||
.rmdir = CIFSSMBRmDir,
|
.rmdir = CIFSSMBRmDir,
|
||||||
.unlink = CIFSSMBDelFile,
|
.unlink = CIFSSMBDelFile,
|
||||||
.rename_pending_delete = cifs_rename_pending_delete,
|
.rename_pending_delete = cifs_rename_pending_delete,
|
||||||
|
.rename = CIFSSMBRename,
|
||||||
.open = cifs_open_file,
|
.open = cifs_open_file,
|
||||||
.set_fid = cifs_set_fid,
|
.set_fid = cifs_set_fid,
|
||||||
.close = cifs_close_file,
|
.close = cifs_close_file,
|
||||||
|
|
Reference in New Issue