fs/ntfs3: fix symlinks cannot be handled correctly
The symlinks created in windows will be broken in linux by ntfs3, the patch fixes it. Signed-off-by: Rong Zhang <ulin0208@gmail.com> Signed-off-by: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>pull/1279/head
parent
19272b37aa
commit
8df35e16a9
|
|
@ -329,8 +329,7 @@ static inline bool ntfs_dir_emit(struct ntfs_sb_info *sbi,
|
|||
* It does additional locks/reads just to get the type of name.
|
||||
* Should we use additional mount option to enable branch below?
|
||||
*/
|
||||
if (((fname->dup.fa & FILE_ATTRIBUTE_REPARSE_POINT) ||
|
||||
fname->dup.ea_size) &&
|
||||
if (fname->dup.extend_data &&
|
||||
ino != ni->mi.rno) {
|
||||
struct inode *inode = ntfs_iget5(sbi->sb, &e->ref, NULL);
|
||||
if (!IS_ERR_OR_NULL(inode)) {
|
||||
|
|
|
|||
|
|
@ -3119,11 +3119,21 @@ static bool ni_update_parent(struct ntfs_inode *ni, struct NTFS_DUP_INFO *dup,
|
|||
}
|
||||
}
|
||||
|
||||
/* TODO: Fill reparse info. */
|
||||
dup->reparse = 0;
|
||||
dup->ea_size = 0;
|
||||
dup->extend_data = 0;
|
||||
|
||||
if (ni->ni_flags & NI_FLAG_EA) {
|
||||
if (dup->fa & FILE_ATTRIBUTE_REPARSE_POINT) {
|
||||
attr = ni_find_attr(ni, NULL, NULL, ATTR_REPARSE, NULL, 0, NULL,
|
||||
NULL);
|
||||
|
||||
if (attr) {
|
||||
const struct REPARSE_POINT *rp;
|
||||
|
||||
rp = resident_data_ex(attr, sizeof(struct REPARSE_POINT));
|
||||
/* If ATTR_REPARSE exists 'rp' can't be NULL. */
|
||||
if (rp)
|
||||
dup->extend_data = rp->ReparseTag;
|
||||
}
|
||||
} else if (ni->ni_flags & NI_FLAG_EA) {
|
||||
attr = ni_find_attr(ni, attr, &le, ATTR_EA_INFO, NULL, 0, NULL,
|
||||
NULL);
|
||||
if (attr) {
|
||||
|
|
@ -3132,7 +3142,7 @@ static bool ni_update_parent(struct ntfs_inode *ni, struct NTFS_DUP_INFO *dup,
|
|||
info = resident_data_ex(attr, sizeof(struct EA_INFO));
|
||||
/* If ATTR_EA_INFO exists 'info' can't be NULL. */
|
||||
if (info)
|
||||
dup->ea_size = info->size_pack;
|
||||
dup->extend_data = info->size;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1350,7 +1350,7 @@ int ntfs_create_inode(struct mnt_idmap *idmap, struct inode *dir,
|
|||
fname->dup.a_time = std5->cr_time;
|
||||
fname->dup.alloc_size = fname->dup.data_size = 0;
|
||||
fname->dup.fa = std5->fa;
|
||||
fname->dup.ea_size = fname->dup.reparse = 0;
|
||||
fname->dup.extend_data = S_ISLNK(mode) ? IO_REPARSE_TAG_SYMLINK : 0;
|
||||
|
||||
dsize = le16_to_cpu(new_de->key_size);
|
||||
asize = ALIGN(SIZEOF_RESIDENT + dsize, 8);
|
||||
|
|
@ -1590,12 +1590,13 @@ int ntfs_create_inode(struct mnt_idmap *idmap, struct inode *dir,
|
|||
inode->i_flags |= S_NOSEC;
|
||||
}
|
||||
|
||||
if (!S_ISLNK(mode)) {
|
||||
/*
|
||||
* ntfs_init_acl and ntfs_save_wsl_perm update extended attribute.
|
||||
* The packed size of extended attribute is stored in direntry too.
|
||||
* 'fname' here points to inside new_de.
|
||||
*/
|
||||
err = ntfs_save_wsl_perm(inode, &fname->dup.ea_size);
|
||||
err = ntfs_save_wsl_perm(inode, &fname->dup.extend_data);
|
||||
if (err)
|
||||
goto out6;
|
||||
|
||||
|
|
@ -1610,7 +1611,8 @@ int ntfs_create_inode(struct mnt_idmap *idmap, struct inode *dir,
|
|||
|
||||
fn = resident_data_ex(attr, SIZEOF_ATTRIBUTE_FILENAME);
|
||||
if (fn)
|
||||
fn->dup.ea_size = fname->dup.ea_size;
|
||||
fn->dup.extend_data = fname->dup.extend_data;
|
||||
}
|
||||
}
|
||||
|
||||
/* We do not need to update parent directory later */
|
||||
|
|
|
|||
|
|
@ -561,8 +561,7 @@ struct NTFS_DUP_INFO {
|
|||
__le64 alloc_size; // 0x20: Data attribute allocated size, multiple of cluster size.
|
||||
__le64 data_size; // 0x28: Data attribute size <= Dataalloc_size.
|
||||
enum FILE_ATTRIBUTE fa; // 0x30: Standard DOS attributes & more.
|
||||
__le16 ea_size; // 0x34: Packed EAs.
|
||||
__le16 reparse; // 0x36: Used by Reparse.
|
||||
__le32 extend_data; // 0x34: Extended data.
|
||||
|
||||
}; // 0x38
|
||||
|
||||
|
|
|
|||
|
|
@ -874,7 +874,7 @@ int ntfs_acl_chmod(struct mnt_idmap *idmap, struct dentry *dentry);
|
|||
ssize_t ntfs_listxattr(struct dentry *dentry, char *buffer, size_t size);
|
||||
extern const struct xattr_handler *const ntfs_xattr_handlers[];
|
||||
|
||||
int ntfs_save_wsl_perm(struct inode *inode, __le16 *ea_size);
|
||||
int ntfs_save_wsl_perm(struct inode *inode, __le32 *ea_size);
|
||||
void ntfs_get_wsl_perm(struct inode *inode);
|
||||
|
||||
/* globals from lznt.c */
|
||||
|
|
|
|||
|
|
@ -313,7 +313,7 @@ out:
|
|||
static noinline int ntfs_set_ea(struct inode *inode, const char *name,
|
||||
size_t name_len, const void *value,
|
||||
size_t val_size, int flags, bool locked,
|
||||
__le16 *ea_size)
|
||||
__le32 *ea_size)
|
||||
{
|
||||
struct ntfs_inode *ni = ntfs_i(inode);
|
||||
struct ntfs_sb_info *sbi = ni->mi.sbi;
|
||||
|
|
@ -522,7 +522,7 @@ update_ea:
|
|||
if (ea_info.size_pack != size_pack)
|
||||
ni->ni_flags |= NI_FLAG_UPDATE_PARENT;
|
||||
if (ea_size)
|
||||
*ea_size = ea_info.size_pack;
|
||||
*ea_size = ea_info.size;
|
||||
mark_inode_dirty(&ni->vfs_inode);
|
||||
|
||||
out:
|
||||
|
|
@ -950,7 +950,7 @@ out:
|
|||
*
|
||||
* save uid/gid/mode in xattr
|
||||
*/
|
||||
int ntfs_save_wsl_perm(struct inode *inode, __le16 *ea_size)
|
||||
int ntfs_save_wsl_perm(struct inode *inode, __le32 *ea_size)
|
||||
{
|
||||
int err;
|
||||
__le32 value;
|
||||
|
|
|
|||
Loading…
Reference in New Issue