diff options
-rw-r--r-- | fs/cifs/cifsglob.h | 3 | ||||
-rw-r--r-- | fs/cifs/cifsproto.h | 5 | ||||
-rw-r--r-- | fs/cifs/cifssmb.c | 22 | ||||
-rw-r--r-- | fs/cifs/inode.c | 92 | ||||
-rw-r--r-- | fs/cifs/smb1ops.c | 1 |
5 files changed, 66 insertions, 57 deletions
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index 6217df707909..a0105c547ffd 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h | |||
@@ -275,6 +275,9 @@ struct smb_version_operations { | |||
275 | /* open, rename and delete file */ | 275 | /* open, rename and delete file */ |
276 | int (*rename_pending_delete)(const char *, struct dentry *, | 276 | int (*rename_pending_delete)(const char *, struct dentry *, |
277 | const unsigned int); | 277 | const unsigned int); |
278 | /* send rename request */ | ||
279 | int (*rename)(const unsigned int, struct cifs_tcon *, const char *, | ||
280 | const char *, struct cifs_sb_info *); | ||
278 | /* open a file for non-posix mounts */ | 281 | /* open a file for non-posix mounts */ |
279 | int (*open)(const unsigned int, struct cifs_tcon *, const char *, int, | 282 | int (*open)(const unsigned int, struct cifs_tcon *, const char *, int, |
280 | int, int, struct cifs_fid *, __u32 *, FILE_ALL_INFO *, | 283 | int, int, struct cifs_fid *, __u32 *, FILE_ALL_INFO *, |
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 541738fcaebc..eecd233c6912 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h | |||
@@ -310,9 +310,8 @@ extern int CIFSPOSIXDelFile(const unsigned int xid, struct cifs_tcon *tcon, | |||
310 | extern int CIFSSMBDelFile(const unsigned int xid, struct cifs_tcon *tcon, | 310 | extern int CIFSSMBDelFile(const unsigned int xid, struct cifs_tcon *tcon, |
311 | const char *name, struct cifs_sb_info *cifs_sb); | 311 | const char *name, struct cifs_sb_info *cifs_sb); |
312 | extern int CIFSSMBRename(const unsigned int xid, struct cifs_tcon *tcon, | 312 | extern int CIFSSMBRename(const unsigned int xid, struct cifs_tcon *tcon, |
313 | const char *fromName, const char *toName, | 313 | const char *from_name, const char *to_name, |
314 | const struct nls_table *nls_codepage, | 314 | struct cifs_sb_info *cifs_sb); |
315 | int remap_special_chars); | ||
316 | extern int CIFSSMBRenameOpenFile(const unsigned int xid, struct cifs_tcon *tcon, | 315 | extern int CIFSSMBRenameOpenFile(const unsigned int xid, struct cifs_tcon *tcon, |
317 | int netfid, const char *target_name, | 316 | int netfid, const char *target_name, |
318 | const struct nls_table *nls_codepage, | 317 | const struct nls_table *nls_codepage, |
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 733119dad493..b8cd335d6f11 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c | |||
@@ -2531,8 +2531,8 @@ CIFSSMBFlush(const unsigned int xid, struct cifs_tcon *tcon, int smb_file_id) | |||
2531 | 2531 | ||
2532 | int | 2532 | int |
2533 | CIFSSMBRename(const unsigned int xid, struct cifs_tcon *tcon, | 2533 | CIFSSMBRename(const unsigned int xid, struct cifs_tcon *tcon, |
2534 | const char *fromName, const char *toName, | 2534 | const char *from_name, const char *to_name, |
2535 | const struct nls_table *nls_codepage, int remap) | 2535 | struct cifs_sb_info *cifs_sb) |
2536 | { | 2536 | { |
2537 | int rc = 0; | 2537 | int rc = 0; |
2538 | RENAME_REQ *pSMB = NULL; | 2538 | RENAME_REQ *pSMB = NULL; |
@@ -2540,6 +2540,7 @@ CIFSSMBRename(const unsigned int xid, struct cifs_tcon *tcon, | |||
2540 | int bytes_returned; | 2540 | int bytes_returned; |
2541 | int name_len, name_len2; | 2541 | int name_len, name_len2; |
2542 | __u16 count; | 2542 | __u16 count; |
2543 | int remap = cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR; | ||
2543 | 2544 | ||
2544 | cFYI(1, "In CIFSSMBRename"); | 2545 | cFYI(1, "In CIFSSMBRename"); |
2545 | renameRetry: | 2546 | renameRetry: |
@@ -2554,9 +2555,9 @@ renameRetry: | |||
2554 | ATTR_DIRECTORY); | 2555 | ATTR_DIRECTORY); |
2555 | 2556 | ||
2556 | if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { | 2557 | if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { |
2557 | name_len = | 2558 | name_len = cifsConvertToUTF16((__le16 *) pSMB->OldFileName, |
2558 | cifsConvertToUTF16((__le16 *) pSMB->OldFileName, fromName, | 2559 | from_name, PATH_MAX, |
2559 | PATH_MAX, nls_codepage, remap); | 2560 | cifs_sb->local_nls, remap); |
2560 | name_len++; /* trailing null */ | 2561 | name_len++; /* trailing null */ |
2561 | name_len *= 2; | 2562 | name_len *= 2; |
2562 | pSMB->OldFileName[name_len] = 0x04; /* pad */ | 2563 | pSMB->OldFileName[name_len] = 0x04; /* pad */ |
@@ -2564,17 +2565,18 @@ renameRetry: | |||
2564 | pSMB->OldFileName[name_len + 1] = 0x00; | 2565 | pSMB->OldFileName[name_len + 1] = 0x00; |
2565 | name_len2 = | 2566 | name_len2 = |
2566 | cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2], | 2567 | cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2], |
2567 | toName, PATH_MAX, nls_codepage, remap); | 2568 | to_name, PATH_MAX, cifs_sb->local_nls, |
2569 | remap); | ||
2568 | name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ; | 2570 | name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ; |
2569 | name_len2 *= 2; /* convert to bytes */ | 2571 | name_len2 *= 2; /* convert to bytes */ |
2570 | } else { /* BB improve the check for buffer overruns BB */ | 2572 | } else { /* BB improve the check for buffer overruns BB */ |
2571 | name_len = strnlen(fromName, PATH_MAX); | 2573 | name_len = strnlen(from_name, PATH_MAX); |
2572 | name_len++; /* trailing null */ | 2574 | name_len++; /* trailing null */ |
2573 | strncpy(pSMB->OldFileName, fromName, name_len); | 2575 | strncpy(pSMB->OldFileName, from_name, name_len); |
2574 | name_len2 = strnlen(toName, PATH_MAX); | 2576 | name_len2 = strnlen(to_name, PATH_MAX); |
2575 | name_len2++; /* trailing null */ | 2577 | name_len2++; /* trailing null */ |
2576 | pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */ | 2578 | pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */ |
2577 | strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2); | 2579 | strncpy(&pSMB->OldFileName[name_len + 1], to_name, name_len2); |
2578 | name_len2++; /* trailing null */ | 2580 | name_len2++; /* trailing null */ |
2579 | name_len2++; /* signature byte */ | 2581 | name_len2++; /* signature byte */ |
2580 | } | 2582 | } |
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index c6f6b02cf3b5..2f3235f08c3f 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c | |||
@@ -1512,29 +1512,32 @@ rmdir_exit: | |||
1512 | } | 1512 | } |
1513 | 1513 | ||
1514 | static int | 1514 | static int |
1515 | cifs_do_rename(unsigned int xid, struct dentry *from_dentry, | 1515 | cifs_do_rename(const unsigned int xid, struct dentry *from_dentry, |
1516 | const char *fromPath, struct dentry *to_dentry, | 1516 | const char *from_path, struct dentry *to_dentry, |
1517 | const char *toPath) | 1517 | const char *to_path) |
1518 | { | 1518 | { |
1519 | struct cifs_sb_info *cifs_sb = CIFS_SB(from_dentry->d_sb); | 1519 | struct cifs_sb_info *cifs_sb = CIFS_SB(from_dentry->d_sb); |
1520 | struct tcon_link *tlink; | 1520 | struct tcon_link *tlink; |
1521 | struct cifs_tcon *pTcon; | 1521 | struct cifs_tcon *tcon; |
1522 | struct TCP_Server_Info *server; | ||
1522 | __u16 srcfid; | 1523 | __u16 srcfid; |
1523 | int oplock, rc; | 1524 | int oplock, rc; |
1524 | 1525 | ||
1525 | tlink = cifs_sb_tlink(cifs_sb); | 1526 | tlink = cifs_sb_tlink(cifs_sb); |
1526 | if (IS_ERR(tlink)) | 1527 | if (IS_ERR(tlink)) |
1527 | return PTR_ERR(tlink); | 1528 | return PTR_ERR(tlink); |
1528 | pTcon = tlink_tcon(tlink); | 1529 | tcon = tlink_tcon(tlink); |
1530 | server = tcon->ses->server; | ||
1531 | |||
1532 | if (!server->ops->rename) | ||
1533 | return -ENOSYS; | ||
1529 | 1534 | ||
1530 | /* try path-based rename first */ | 1535 | /* try path-based rename first */ |
1531 | rc = CIFSSMBRename(xid, pTcon, fromPath, toPath, cifs_sb->local_nls, | 1536 | rc = server->ops->rename(xid, tcon, from_path, to_path, cifs_sb); |
1532 | cifs_sb->mnt_cifs_flags & | ||
1533 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
1534 | 1537 | ||
1535 | /* | 1538 | /* |
1536 | * don't bother with rename by filehandle unless file is busy and | 1539 | * Don't bother with rename by filehandle unless file is busy and |
1537 | * source Note that cross directory moves do not work with | 1540 | * source. Note that cross directory moves do not work with |
1538 | * rename by filehandle to various Windows servers. | 1541 | * rename by filehandle to various Windows servers. |
1539 | */ | 1542 | */ |
1540 | if (rc == 0 || rc != -ETXTBSY) | 1543 | if (rc == 0 || rc != -ETXTBSY) |
@@ -1545,29 +1548,28 @@ cifs_do_rename(unsigned int xid, struct dentry *from_dentry, | |||
1545 | goto do_rename_exit; | 1548 | goto do_rename_exit; |
1546 | 1549 | ||
1547 | /* open the file to be renamed -- we need DELETE perms */ | 1550 | /* open the file to be renamed -- we need DELETE perms */ |
1548 | rc = CIFSSMBOpen(xid, pTcon, fromPath, FILE_OPEN, DELETE, | 1551 | rc = CIFSSMBOpen(xid, tcon, from_path, FILE_OPEN, DELETE, |
1549 | CREATE_NOT_DIR, &srcfid, &oplock, NULL, | 1552 | CREATE_NOT_DIR, &srcfid, &oplock, NULL, |
1550 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & | 1553 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & |
1551 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 1554 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
1552 | |||
1553 | if (rc == 0) { | 1555 | if (rc == 0) { |
1554 | rc = CIFSSMBRenameOpenFile(xid, pTcon, srcfid, | 1556 | rc = CIFSSMBRenameOpenFile(xid, tcon, srcfid, |
1555 | (const char *) to_dentry->d_name.name, | 1557 | (const char *) to_dentry->d_name.name, |
1556 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & | 1558 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & |
1557 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 1559 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
1558 | 1560 | CIFSSMBClose(xid, tcon, srcfid); | |
1559 | CIFSSMBClose(xid, pTcon, srcfid); | ||
1560 | } | 1561 | } |
1561 | do_rename_exit: | 1562 | do_rename_exit: |
1562 | cifs_put_tlink(tlink); | 1563 | cifs_put_tlink(tlink); |
1563 | return rc; | 1564 | return rc; |
1564 | } | 1565 | } |
1565 | 1566 | ||
1566 | int cifs_rename(struct inode *source_dir, struct dentry *source_dentry, | 1567 | int |
1567 | struct inode *target_dir, struct dentry *target_dentry) | 1568 | cifs_rename(struct inode *source_dir, struct dentry *source_dentry, |
1569 | struct inode *target_dir, struct dentry *target_dentry) | ||
1568 | { | 1570 | { |
1569 | char *fromName = NULL; | 1571 | char *from_name = NULL; |
1570 | char *toName = NULL; | 1572 | char *to_name = NULL; |
1571 | struct cifs_sb_info *cifs_sb; | 1573 | struct cifs_sb_info *cifs_sb; |
1572 | struct tcon_link *tlink; | 1574 | struct tcon_link *tlink; |
1573 | struct cifs_tcon *tcon; | 1575 | struct cifs_tcon *tcon; |
@@ -1588,25 +1590,25 @@ int cifs_rename(struct inode *source_dir, struct dentry *source_dentry, | |||
1588 | * we already have the rename sem so we do not need to | 1590 | * we already have the rename sem so we do not need to |
1589 | * grab it again here to protect the path integrity | 1591 | * grab it again here to protect the path integrity |
1590 | */ | 1592 | */ |
1591 | fromName = build_path_from_dentry(source_dentry); | 1593 | from_name = build_path_from_dentry(source_dentry); |
1592 | if (fromName == NULL) { | 1594 | if (from_name == NULL) { |
1593 | rc = -ENOMEM; | 1595 | rc = -ENOMEM; |
1594 | goto cifs_rename_exit; | 1596 | goto cifs_rename_exit; |
1595 | } | 1597 | } |
1596 | 1598 | ||
1597 | toName = build_path_from_dentry(target_dentry); | 1599 | to_name = build_path_from_dentry(target_dentry); |
1598 | if (toName == NULL) { | 1600 | if (to_name == NULL) { |
1599 | rc = -ENOMEM; | 1601 | rc = -ENOMEM; |
1600 | goto cifs_rename_exit; | 1602 | goto cifs_rename_exit; |
1601 | } | 1603 | } |
1602 | 1604 | ||
1603 | rc = cifs_do_rename(xid, source_dentry, fromName, | 1605 | rc = cifs_do_rename(xid, source_dentry, from_name, target_dentry, |
1604 | target_dentry, toName); | 1606 | to_name); |
1605 | 1607 | ||
1606 | if (rc == -EEXIST && tcon->unix_ext) { | 1608 | if (rc == -EEXIST && tcon->unix_ext) { |
1607 | /* | 1609 | /* |
1608 | * Are src and dst hardlinks of same inode? We can | 1610 | * Are src and dst hardlinks of same inode? We can only tell |
1609 | * only tell with unix extensions enabled | 1611 | * with unix extensions enabled. |
1610 | */ | 1612 | */ |
1611 | info_buf_source = | 1613 | info_buf_source = |
1612 | kmalloc(2 * sizeof(FILE_UNIX_BASIC_INFO), | 1614 | kmalloc(2 * sizeof(FILE_UNIX_BASIC_INFO), |
@@ -1617,19 +1619,19 @@ int cifs_rename(struct inode *source_dir, struct dentry *source_dentry, | |||
1617 | } | 1619 | } |
1618 | 1620 | ||
1619 | info_buf_target = info_buf_source + 1; | 1621 | info_buf_target = info_buf_source + 1; |
1620 | tmprc = CIFSSMBUnixQPathInfo(xid, tcon, fromName, | 1622 | tmprc = CIFSSMBUnixQPathInfo(xid, tcon, from_name, |
1621 | info_buf_source, | 1623 | info_buf_source, |
1622 | cifs_sb->local_nls, | 1624 | cifs_sb->local_nls, |
1623 | cifs_sb->mnt_cifs_flags & | 1625 | cifs_sb->mnt_cifs_flags & |
1624 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 1626 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
1625 | if (tmprc != 0) | 1627 | if (tmprc != 0) |
1626 | goto unlink_target; | 1628 | goto unlink_target; |
1627 | 1629 | ||
1628 | tmprc = CIFSSMBUnixQPathInfo(xid, tcon, toName, | 1630 | tmprc = CIFSSMBUnixQPathInfo(xid, tcon, to_name, |
1629 | info_buf_target, | 1631 | info_buf_target, |
1630 | cifs_sb->local_nls, | 1632 | cifs_sb->local_nls, |
1631 | cifs_sb->mnt_cifs_flags & | 1633 | cifs_sb->mnt_cifs_flags & |
1632 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 1634 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
1633 | 1635 | ||
1634 | if (tmprc == 0 && (info_buf_source->UniqueId == | 1636 | if (tmprc == 0 && (info_buf_source->UniqueId == |
1635 | info_buf_target->UniqueId)) { | 1637 | info_buf_target->UniqueId)) { |
@@ -1637,8 +1639,11 @@ int cifs_rename(struct inode *source_dir, struct dentry *source_dentry, | |||
1637 | rc = 0; | 1639 | rc = 0; |
1638 | goto cifs_rename_exit; | 1640 | goto cifs_rename_exit; |
1639 | } | 1641 | } |
1640 | } /* else ... BB we could add the same check for Windows by | 1642 | } |
1641 | checking the UniqueId via FILE_INTERNAL_INFO */ | 1643 | /* |
1644 | * else ... BB we could add the same check for Windows by | ||
1645 | * checking the UniqueId via FILE_INTERNAL_INFO | ||
1646 | */ | ||
1642 | 1647 | ||
1643 | unlink_target: | 1648 | unlink_target: |
1644 | /* Try unlinking the target dentry if it's not negative */ | 1649 | /* Try unlinking the target dentry if it's not negative */ |
@@ -1646,15 +1651,14 @@ unlink_target: | |||
1646 | tmprc = cifs_unlink(target_dir, target_dentry); | 1651 | tmprc = cifs_unlink(target_dir, target_dentry); |
1647 | if (tmprc) | 1652 | if (tmprc) |
1648 | goto cifs_rename_exit; | 1653 | goto cifs_rename_exit; |
1649 | 1654 | rc = cifs_do_rename(xid, source_dentry, from_name, | |
1650 | rc = cifs_do_rename(xid, source_dentry, fromName, | 1655 | target_dentry, to_name); |
1651 | target_dentry, toName); | ||
1652 | } | 1656 | } |
1653 | 1657 | ||
1654 | cifs_rename_exit: | 1658 | cifs_rename_exit: |
1655 | kfree(info_buf_source); | 1659 | kfree(info_buf_source); |
1656 | kfree(fromName); | 1660 | kfree(from_name); |
1657 | kfree(toName); | 1661 | kfree(to_name); |
1658 | free_xid(xid); | 1662 | free_xid(xid); |
1659 | cifs_put_tlink(tlink); | 1663 | cifs_put_tlink(tlink); |
1660 | return rc; | 1664 | return rc; |
diff --git a/fs/cifs/smb1ops.c b/fs/cifs/smb1ops.c index aa55c2fbf793..377392003655 100644 --- a/fs/cifs/smb1ops.c +++ b/fs/cifs/smb1ops.c | |||
@@ -800,6 +800,7 @@ struct smb_version_operations smb1_operations = { | |||
800 | .rmdir = CIFSSMBRmDir, | 800 | .rmdir = CIFSSMBRmDir, |
801 | .unlink = CIFSSMBDelFile, | 801 | .unlink = CIFSSMBDelFile, |
802 | .rename_pending_delete = cifs_rename_pending_delete, | 802 | .rename_pending_delete = cifs_rename_pending_delete, |
803 | .rename = CIFSSMBRename, | ||
803 | .open = cifs_open_file, | 804 | .open = cifs_open_file, |
804 | .set_fid = cifs_set_fid, | 805 | .set_fid = cifs_set_fid, |
805 | .close = cifs_close_file, | 806 | .close = cifs_close_file, |