Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 326272
b: refs/heads/master
c: 8ceb984
h: refs/heads/master
v: v3
  • Loading branch information
Pavel Shilovsky authored and Steve French committed Sep 25, 2012
1 parent 2f5d709 commit e5f44a3
Show file tree
Hide file tree
Showing 6 changed files with 67 additions and 58 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 3c1bf7e48e9e463b65b1b90da4500a93dd2b27a7
refs/heads/master: 8ceb984379462f94bdebef3288d569c6e1f912ea
3 changes: 3 additions & 0 deletions trunk/fs/cifs/cifsglob.h
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,9 @@ struct smb_version_operations {
/* open, rename and delete file */
int (*rename_pending_delete)(const char *, struct dentry *,
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 */
int (*open)(const unsigned int, struct cifs_tcon *, const char *, int,
int, int, struct cifs_fid *, __u32 *, FILE_ALL_INFO *,
Expand Down
5 changes: 2 additions & 3 deletions trunk/fs/cifs/cifsproto.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
const char *name, struct cifs_sb_info *cifs_sb);
extern int CIFSSMBRename(const unsigned int xid, struct cifs_tcon *tcon,
const char *fromName, const char *toName,
const struct nls_table *nls_codepage,
int remap_special_chars);
const char *from_name, const char *to_name,
struct cifs_sb_info *cifs_sb);
extern int CIFSSMBRenameOpenFile(const unsigned int xid, struct cifs_tcon *tcon,
int netfid, const char *target_name,
const struct nls_table *nls_codepage,
Expand Down
22 changes: 12 additions & 10 deletions trunk/fs/cifs/cifssmb.c
Original file line number Diff line number Diff line change
Expand Up @@ -2531,15 +2531,16 @@ CIFSSMBFlush(const unsigned int xid, struct cifs_tcon *tcon, int smb_file_id)

int
CIFSSMBRename(const unsigned int xid, struct cifs_tcon *tcon,
const char *fromName, const char *toName,
const struct nls_table *nls_codepage, int remap)
const char *from_name, const char *to_name,
struct cifs_sb_info *cifs_sb)
{
int rc = 0;
RENAME_REQ *pSMB = NULL;
RENAME_RSP *pSMBr = NULL;
int bytes_returned;
int name_len, name_len2;
__u16 count;
int remap = cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR;

cFYI(1, "In CIFSSMBRename");
renameRetry:
Expand All @@ -2554,27 +2555,28 @@ CIFSSMBRename(const unsigned int xid, struct cifs_tcon *tcon,
ATTR_DIRECTORY);

if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len =
cifsConvertToUTF16((__le16 *) pSMB->OldFileName, fromName,
PATH_MAX, nls_codepage, remap);
name_len = cifsConvertToUTF16((__le16 *) pSMB->OldFileName,
from_name, PATH_MAX,
cifs_sb->local_nls, remap);
name_len++; /* trailing null */
name_len *= 2;
pSMB->OldFileName[name_len] = 0x04; /* pad */
/* protocol requires ASCII signature byte on Unicode string */
pSMB->OldFileName[name_len + 1] = 0x00;
name_len2 =
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 *= 2; /* convert to bytes */
} 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 */
strncpy(pSMB->OldFileName, fromName, name_len);
name_len2 = strnlen(toName, PATH_MAX);
strncpy(pSMB->OldFileName, from_name, name_len);
name_len2 = strnlen(to_name, PATH_MAX);
name_len2++; /* trailing null */
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++; /* signature byte */
}
Expand Down
92 changes: 48 additions & 44 deletions trunk/fs/cifs/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -1512,29 +1512,32 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry)
}

static int
cifs_do_rename(unsigned int xid, struct dentry *from_dentry,
const char *fromPath, struct dentry *to_dentry,
const char *toPath)
cifs_do_rename(const unsigned int xid, struct dentry *from_dentry,
const char *from_path, struct dentry *to_dentry,
const char *to_path)
{
struct cifs_sb_info *cifs_sb = CIFS_SB(from_dentry->d_sb);
struct tcon_link *tlink;
struct cifs_tcon *pTcon;
struct cifs_tcon *tcon;
struct TCP_Server_Info *server;
__u16 srcfid;
int oplock, rc;

tlink = cifs_sb_tlink(cifs_sb);
if (IS_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 */
rc = CIFSSMBRename(xid, pTcon, fromPath, toPath, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
rc = server->ops->rename(xid, tcon, from_path, to_path, cifs_sb);

/*
* don't bother with rename by filehandle unless file is busy and
* source Note that cross directory moves do not work with
* Don't bother with rename by filehandle unless file is busy and
* source. Note that cross directory moves do not work with
* rename by filehandle to various Windows servers.
*/
if (rc == 0 || rc != -ETXTBSY)
Expand All @@ -1545,29 +1548,28 @@ cifs_do_rename(unsigned int xid, struct dentry *from_dentry,
goto do_rename_exit;

/* 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,
cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);

if (rc == 0) {
rc = CIFSSMBRenameOpenFile(xid, pTcon, srcfid,
rc = CIFSSMBRenameOpenFile(xid, tcon, srcfid,
(const char *) to_dentry->d_name.name,
cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);

CIFSSMBClose(xid, pTcon, srcfid);
CIFSSMBClose(xid, tcon, srcfid);
}
do_rename_exit:
cifs_put_tlink(tlink);
return rc;
}

int cifs_rename(struct inode *source_dir, struct dentry *source_dentry,
struct inode *target_dir, struct dentry *target_dentry)
int
cifs_rename(struct inode *source_dir, struct dentry *source_dentry,
struct inode *target_dir, struct dentry *target_dentry)
{
char *fromName = NULL;
char *toName = NULL;
char *from_name = NULL;
char *to_name = NULL;
struct cifs_sb_info *cifs_sb;
struct tcon_link *tlink;
struct cifs_tcon *tcon;
Expand All @@ -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
* grab it again here to protect the path integrity
*/
fromName = build_path_from_dentry(source_dentry);
if (fromName == NULL) {
from_name = build_path_from_dentry(source_dentry);
if (from_name == NULL) {
rc = -ENOMEM;
goto cifs_rename_exit;
}

toName = build_path_from_dentry(target_dentry);
if (toName == NULL) {
to_name = build_path_from_dentry(target_dentry);
if (to_name == NULL) {
rc = -ENOMEM;
goto cifs_rename_exit;
}

rc = cifs_do_rename(xid, source_dentry, fromName,
target_dentry, toName);
rc = cifs_do_rename(xid, source_dentry, from_name, target_dentry,
to_name);

if (rc == -EEXIST && tcon->unix_ext) {
/*
* Are src and dst hardlinks of same inode? We can
* only tell with unix extensions enabled
* Are src and dst hardlinks of same inode? We can only tell
* with unix extensions enabled.
*/
info_buf_source =
kmalloc(2 * sizeof(FILE_UNIX_BASIC_INFO),
Expand All @@ -1617,44 +1619,46 @@ int cifs_rename(struct inode *source_dir, struct dentry *source_dentry,
}

info_buf_target = info_buf_source + 1;
tmprc = CIFSSMBUnixQPathInfo(xid, tcon, fromName,
info_buf_source,
cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
tmprc = CIFSSMBUnixQPathInfo(xid, tcon, from_name,
info_buf_source,
cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
if (tmprc != 0)
goto unlink_target;

tmprc = CIFSSMBUnixQPathInfo(xid, tcon, toName,
info_buf_target,
cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
tmprc = CIFSSMBUnixQPathInfo(xid, tcon, to_name,
info_buf_target,
cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);

if (tmprc == 0 && (info_buf_source->UniqueId ==
info_buf_target->UniqueId)) {
/* same file, POSIX says that this is a noop */
rc = 0;
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:
/* Try unlinking the target dentry if it's not negative */
if (target_dentry->d_inode && (rc == -EACCES || rc == -EEXIST)) {
tmprc = cifs_unlink(target_dir, target_dentry);
if (tmprc)
goto cifs_rename_exit;

rc = cifs_do_rename(xid, source_dentry, fromName,
target_dentry, toName);
rc = cifs_do_rename(xid, source_dentry, from_name,
target_dentry, to_name);
}

cifs_rename_exit:
kfree(info_buf_source);
kfree(fromName);
kfree(toName);
kfree(from_name);
kfree(to_name);
free_xid(xid);
cifs_put_tlink(tlink);
return rc;
Expand Down
1 change: 1 addition & 0 deletions trunk/fs/cifs/smb1ops.c
Original file line number Diff line number Diff line change
Expand Up @@ -800,6 +800,7 @@ struct smb_version_operations smb1_operations = {
.rmdir = CIFSSMBRmDir,
.unlink = CIFSSMBDelFile,
.rename_pending_delete = cifs_rename_pending_delete,
.rename = CIFSSMBRename,
.open = cifs_open_file,
.set_fid = cifs_set_fid,
.close = cifs_close_file,
Expand Down

0 comments on commit e5f44a3

Please sign in to comment.