When creating a symlink, ntfs3 converts all the '/' to '\' in both PrintName and SubstituteName. When reading this symlink, ntfs3 converts all the '\' to '/'. So if you create a symlink to 'a\b', the result of readlink would be 'a/b'. Fix this by converting SubstituteName only because SubstituteName is used by NT kernel to read symlink while PrintName isn't; PrintName is left unchanged to ensure consistency. Signed-off-by: Zhenyan Wang --- fs/ntfs3/inode.c | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/fs/ntfs3/inode.c b/fs/ntfs3/inode.c index 6717563..000ac34 100644 --- a/fs/ntfs3/inode.c +++ b/fs/ntfs3/inode.c @@ -1091,6 +1091,7 @@ ntfs_create_reparse_buffer(struct ntfs_sb_info *sbi, const char *symname, int i, err; struct REPARSE_DATA_BUFFER *rp; __le16 *rp_name; + __le16 *sub_name; typeof(rp->SymbolicLinkReparseBuffer) *rs; bool is_absolute; @@ -1118,12 +1119,6 @@ ntfs_create_reparse_buffer(struct ntfs_sb_info *sbi, const char *symname, goto out; } - /* Translate Linux '/' into Windows '\'. */ - for (i = 0; i < err; i++) { - if (rp_name[i] == cpu_to_le16('/')) - rp_name[i] = cpu_to_le16('\\'); - } - rp->ReparseTag = IO_REPARSE_TAG_SYMLINK; rp->ReparseDataLength = cpu_to_le16(*nsize - offsetof(struct REPARSE_DATA_BUFFER, @@ -1142,9 +1137,16 @@ ntfs_create_reparse_buffer(struct ntfs_sb_info *sbi, const char *symname, */ rs->Flags = cpu_to_le32(is_absolute ? 0 : SYMLINK_FLAG_RELATIVE); - memmove(rp_name + err + (is_absolute ? 4 : 0), rp_name, + sub_name = rp_name + err + (is_absolute ? 4 : 0); + memmove(sub_name, rp_name, sizeof(short) * err); + /* Translate Linux '/' into Windows '\'. */ + for (i = 0; i < err; i++) { + if (sub_name[i] == cpu_to_le16('/')) + sub_name[i] = cpu_to_le16('\\'); + } + if (is_absolute) { /* Decorate SubstituteName. */ rp_name += err; @@ -2031,12 +2033,6 @@ static noinline int ntfs_readlink_hlp(const struct dentry *link_de, if (err < 0) goto out; - /* Translate Windows '\' into Linux '/'. */ - for (i = 0; i < err; i++) { - if (buffer[i] == '\\') - buffer[i] = '/'; - } - /* Always set last zero. */ buffer[err] = 0; -- 2.53.0