|
Kmods SIG |
d83023 |
From 78ab59fee07f22464f32eafebab2bd97ba94ff2d Mon Sep 17 00:00:00 2001
|
|
Kmods SIG |
d83023 |
From: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
|
|
Kmods SIG |
d83023 |
Date: Tue, 31 Aug 2021 18:52:39 +0300
|
|
Kmods SIG |
d83023 |
Subject: [Backport 78ab59fee07f] src: Rework file operations
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
Rename now works "Add new name and remove old name".
|
|
Kmods SIG |
d83023 |
"Remove old name and add new name" may result in bad inode
|
|
Kmods SIG |
d83023 |
if we can't add new name and then can't restore (add) old name.
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
Signed-off-by: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
|
|
Kmods SIG |
d83023 |
---
|
|
Kmods SIG |
d83023 |
src/attrib.c | 17 +--
|
|
Kmods SIG |
d83023 |
src/attrlist.c | 26 ++--
|
|
Kmods SIG |
d83023 |
src/frecord.c | 342 ++++++++++++++++++++++++++++++++++++--------
|
|
Kmods SIG |
d83023 |
src/fsntfs.c | 87 +++++------
|
|
Kmods SIG |
d83023 |
src/index.c | 45 +++---
|
|
Kmods SIG |
d83023 |
src/inode.c | 275 ++++++++++++-----------------------
|
|
Kmods SIG |
d83023 |
src/namei.c | 236 ++++++++----------------------
|
|
Kmods SIG |
d83023 |
src/ntfs_fs.h | 31 +++-
|
|
Kmods SIG |
d83023 |
src/record.c | 8 +-
|
|
Kmods SIG |
d83023 |
src/xattr.c | 25 ++--
|
|
Kmods SIG |
d83023 |
10 files changed, 563 insertions(+), 529 deletions(-)
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
diff --git a/src/attrib.c b/src/attrib.c
|
|
Kmods SIG |
d83023 |
index 4b285f704e621ef5cbba11f1a006622e6387ea09..ffc323bacc9fe63683395d9535ec65849137551a 100644
|
|
Kmods SIG |
d83023 |
--- a/src/attrib.c
|
|
Kmods SIG |
d83023 |
+++ b/src/attrib.c
|
|
Kmods SIG |
d83023 |
@@ -218,9 +218,11 @@ int attr_allocate_clusters(struct ntfs_sb_info *sbi, struct runs_tree *run,
|
|
Kmods SIG |
d83023 |
}
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
out:
|
|
Kmods SIG |
d83023 |
- /* Undo. */
|
|
Kmods SIG |
d83023 |
- run_deallocate_ex(sbi, run, vcn0, vcn - vcn0, NULL, false);
|
|
Kmods SIG |
d83023 |
- run_truncate(run, vcn0);
|
|
Kmods SIG |
d83023 |
+ /* Undo 'ntfs_look_for_free_space' */
|
|
Kmods SIG |
d83023 |
+ if (vcn - vcn0) {
|
|
Kmods SIG |
d83023 |
+ run_deallocate_ex(sbi, run, vcn0, vcn - vcn0, NULL, false);
|
|
Kmods SIG |
d83023 |
+ run_truncate(run, vcn0);
|
|
Kmods SIG |
d83023 |
+ }
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
return err;
|
|
Kmods SIG |
d83023 |
}
|
|
Kmods SIG |
d83023 |
@@ -701,7 +703,7 @@ int attr_set_size(struct ntfs_inode *ni, enum ATTR_TYPE type,
|
|
Kmods SIG |
d83023 |
* (list entry for std attribute always first).
|
|
Kmods SIG |
d83023 |
* So it is safe to step back.
|
|
Kmods SIG |
d83023 |
*/
|
|
Kmods SIG |
d83023 |
- mi_remove_attr(mi, attr);
|
|
Kmods SIG |
d83023 |
+ mi_remove_attr(NULL, mi, attr);
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
if (!al_remove_le(ni, le)) {
|
|
Kmods SIG |
d83023 |
err = -EINVAL;
|
|
Kmods SIG |
d83023 |
@@ -1004,7 +1006,7 @@ int attr_data_get_block(struct ntfs_inode *ni, CLST vcn, CLST clen, CLST *lcn,
|
|
Kmods SIG |
d83023 |
end = next_svcn;
|
|
Kmods SIG |
d83023 |
while (end > evcn) {
|
|
Kmods SIG |
d83023 |
/* Remove segment [svcn : evcn). */
|
|
Kmods SIG |
d83023 |
- mi_remove_attr(mi, attr);
|
|
Kmods SIG |
d83023 |
+ mi_remove_attr(NULL, mi, attr);
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
if (!al_remove_le(ni, le)) {
|
|
Kmods SIG |
d83023 |
err = -EINVAL;
|
|
Kmods SIG |
d83023 |
@@ -1600,7 +1602,7 @@ int attr_allocate_frame(struct ntfs_inode *ni, CLST frame, size_t compr_size,
|
|
Kmods SIG |
d83023 |
end = next_svcn;
|
|
Kmods SIG |
d83023 |
while (end > evcn) {
|
|
Kmods SIG |
d83023 |
/* Remove segment [svcn : evcn). */
|
|
Kmods SIG |
d83023 |
- mi_remove_attr(mi, attr);
|
|
Kmods SIG |
d83023 |
+ mi_remove_attr(NULL, mi, attr);
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
if (!al_remove_le(ni, le)) {
|
|
Kmods SIG |
d83023 |
err = -EINVAL;
|
|
Kmods SIG |
d83023 |
@@ -1836,13 +1838,12 @@ int attr_collapse_range(struct ntfs_inode *ni, u64 vbo, u64 bytes)
|
|
Kmods SIG |
d83023 |
u16 le_sz;
|
|
Kmods SIG |
d83023 |
u16 roff = le16_to_cpu(attr->nres.run_off);
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
- /* run==1 means unpack and deallocate. */
|
|
Kmods SIG |
d83023 |
run_unpack_ex(RUN_DEALLOCATE, sbi, ni->mi.rno, svcn,
|
|
Kmods SIG |
d83023 |
evcn1 - 1, svcn, Add2Ptr(attr, roff),
|
|
Kmods SIG |
d83023 |
le32_to_cpu(attr->size) - roff);
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
/* Delete this attribute segment. */
|
|
Kmods SIG |
d83023 |
- mi_remove_attr(mi, attr);
|
|
Kmods SIG |
d83023 |
+ mi_remove_attr(NULL, mi, attr);
|
|
Kmods SIG |
d83023 |
if (!le)
|
|
Kmods SIG |
d83023 |
break;
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
diff --git a/src/attrlist.c b/src/attrlist.c
|
|
Kmods SIG |
d83023 |
index 32ca990af64b53b4e9572d5dd0d6ae5f057760c4..fa32399eb5171ce25f037fbd1bd8e483a37b839c 100644
|
|
Kmods SIG |
d83023 |
--- a/src/attrlist.c
|
|
Kmods SIG |
d83023 |
+++ b/src/attrlist.c
|
|
Kmods SIG |
d83023 |
@@ -279,7 +279,7 @@ int al_add_le(struct ntfs_inode *ni, enum ATTR_TYPE type, const __le16 *name,
|
|
Kmods SIG |
d83023 |
struct ATTR_LIST_ENTRY *le;
|
|
Kmods SIG |
d83023 |
size_t off;
|
|
Kmods SIG |
d83023 |
u16 sz;
|
|
Kmods SIG |
d83023 |
- size_t asize, new_asize;
|
|
Kmods SIG |
d83023 |
+ size_t asize, new_asize, old_size;
|
|
Kmods SIG |
d83023 |
u64 new_size;
|
|
Kmods SIG |
d83023 |
typeof(ni->attr_list) *al = &ni->attr_list;
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
@@ -287,8 +287,9 @@ int al_add_le(struct ntfs_inode *ni, enum ATTR_TYPE type, const __le16 *name,
|
|
Kmods SIG |
d83023 |
* Compute the size of the new 'le'
|
|
Kmods SIG |
d83023 |
*/
|
|
Kmods SIG |
d83023 |
sz = le_size(name_len);
|
|
Kmods SIG |
d83023 |
- new_size = al->size + sz;
|
|
Kmods SIG |
d83023 |
- asize = al_aligned(al->size);
|
|
Kmods SIG |
d83023 |
+ old_size = al->size;
|
|
Kmods SIG |
d83023 |
+ new_size = old_size + sz;
|
|
Kmods SIG |
d83023 |
+ asize = al_aligned(old_size);
|
|
Kmods SIG |
d83023 |
new_asize = al_aligned(new_size);
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
/* Scan forward to the point at which the new 'le' should be inserted. */
|
|
Kmods SIG |
d83023 |
@@ -302,13 +303,14 @@ int al_add_le(struct ntfs_inode *ni, enum ATTR_TYPE type, const __le16 *name,
|
|
Kmods SIG |
d83023 |
return -ENOMEM;
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
memcpy(ptr, al->le, off);
|
|
Kmods SIG |
d83023 |
- memcpy(Add2Ptr(ptr, off + sz), le, al->size - off);
|
|
Kmods SIG |
d83023 |
+ memcpy(Add2Ptr(ptr, off + sz), le, old_size - off);
|
|
Kmods SIG |
d83023 |
le = Add2Ptr(ptr, off);
|
|
Kmods SIG |
d83023 |
kfree(al->le);
|
|
Kmods SIG |
d83023 |
al->le = ptr;
|
|
Kmods SIG |
d83023 |
} else {
|
|
Kmods SIG |
d83023 |
- memmove(Add2Ptr(le, sz), le, al->size - off);
|
|
Kmods SIG |
d83023 |
+ memmove(Add2Ptr(le, sz), le, old_size - off);
|
|
Kmods SIG |
d83023 |
}
|
|
Kmods SIG |
d83023 |
+ *new_le = le;
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
al->size = new_size;
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
@@ -321,23 +323,25 @@ int al_add_le(struct ntfs_inode *ni, enum ATTR_TYPE type, const __le16 *name,
|
|
Kmods SIG |
d83023 |
le->id = id;
|
|
Kmods SIG |
d83023 |
memcpy(le->name, name, sizeof(short) * name_len);
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
- al->dirty = true;
|
|
Kmods SIG |
d83023 |
-
|
|
Kmods SIG |
d83023 |
err = attr_set_size(ni, ATTR_LIST, NULL, 0, &al->run, new_size,
|
|
Kmods SIG |
d83023 |
&new_size, true, &attr);
|
|
Kmods SIG |
d83023 |
- if (err)
|
|
Kmods SIG |
d83023 |
+ if (err) {
|
|
Kmods SIG |
d83023 |
+ /* Undo memmove above. */
|
|
Kmods SIG |
d83023 |
+ memmove(le, Add2Ptr(le, sz), old_size - off);
|
|
Kmods SIG |
d83023 |
+ al->size = old_size;
|
|
Kmods SIG |
d83023 |
return err;
|
|
Kmods SIG |
d83023 |
+ }
|
|
Kmods SIG |
d83023 |
+
|
|
Kmods SIG |
d83023 |
+ al->dirty = true;
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
if (attr && attr->non_res) {
|
|
Kmods SIG |
d83023 |
err = ntfs_sb_write_run(ni->mi.sbi, &al->run, 0, al->le,
|
|
Kmods SIG |
d83023 |
al->size);
|
|
Kmods SIG |
d83023 |
if (err)
|
|
Kmods SIG |
d83023 |
return err;
|
|
Kmods SIG |
d83023 |
+ al->dirty = false;
|
|
Kmods SIG |
d83023 |
}
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
- al->dirty = false;
|
|
Kmods SIG |
d83023 |
- *new_le = le;
|
|
Kmods SIG |
d83023 |
-
|
|
Kmods SIG |
d83023 |
return 0;
|
|
Kmods SIG |
d83023 |
}
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
diff --git a/src/frecord.c b/src/frecord.c
|
|
Kmods SIG |
d83023 |
index 9d374827750b2b39261f5985ec2fbb554ac8f6df..3f48b612ec962c6720fb3d3b3e0d63312f389c81 100644
|
|
Kmods SIG |
d83023 |
--- a/src/frecord.c
|
|
Kmods SIG |
d83023 |
+++ b/src/frecord.c
|
|
Kmods SIG |
d83023 |
@@ -163,7 +163,7 @@ int ni_load_mi_ex(struct ntfs_inode *ni, CLST rno, struct mft_inode **mi)
|
|
Kmods SIG |
d83023 |
/*
|
|
Kmods SIG |
d83023 |
* ni_load_mi - Load mft_inode corresponded list_entry.
|
|
Kmods SIG |
d83023 |
*/
|
|
Kmods SIG |
d83023 |
-int ni_load_mi(struct ntfs_inode *ni, struct ATTR_LIST_ENTRY *le,
|
|
Kmods SIG |
d83023 |
+int ni_load_mi(struct ntfs_inode *ni, const struct ATTR_LIST_ENTRY *le,
|
|
Kmods SIG |
d83023 |
struct mft_inode **mi)
|
|
Kmods SIG |
d83023 |
{
|
|
Kmods SIG |
d83023 |
CLST rno;
|
|
Kmods SIG |
d83023 |
@@ -402,7 +402,7 @@ int ni_remove_attr(struct ntfs_inode *ni, enum ATTR_TYPE type,
|
|
Kmods SIG |
d83023 |
if (!attr)
|
|
Kmods SIG |
d83023 |
return -ENOENT;
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
- mi_remove_attr(&ni->mi, attr);
|
|
Kmods SIG |
d83023 |
+ mi_remove_attr(ni, &ni->mi, attr);
|
|
Kmods SIG |
d83023 |
return 0;
|
|
Kmods SIG |
d83023 |
}
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
@@ -441,7 +441,7 @@ int ni_remove_attr(struct ntfs_inode *ni, enum ATTR_TYPE type,
|
|
Kmods SIG |
d83023 |
if (!attr)
|
|
Kmods SIG |
d83023 |
return -ENOENT;
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
- mi_remove_attr(mi, attr);
|
|
Kmods SIG |
d83023 |
+ mi_remove_attr(ni, mi, attr);
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
if (PtrOffset(ni->attr_list.le, le) >= ni->attr_list.size)
|
|
Kmods SIG |
d83023 |
return 0;
|
|
Kmods SIG |
d83023 |
@@ -454,12 +454,11 @@ int ni_remove_attr(struct ntfs_inode *ni, enum ATTR_TYPE type,
|
|
Kmods SIG |
d83023 |
*
|
|
Kmods SIG |
d83023 |
* Return: Not full constructed attribute or NULL if not possible to create.
|
|
Kmods SIG |
d83023 |
*/
|
|
Kmods SIG |
d83023 |
-static struct ATTRIB *ni_ins_new_attr(struct ntfs_inode *ni,
|
|
Kmods SIG |
d83023 |
- struct mft_inode *mi,
|
|
Kmods SIG |
d83023 |
- struct ATTR_LIST_ENTRY *le,
|
|
Kmods SIG |
d83023 |
- enum ATTR_TYPE type, const __le16 *name,
|
|
Kmods SIG |
d83023 |
- u8 name_len, u32 asize, u16 name_off,
|
|
Kmods SIG |
d83023 |
- CLST svcn)
|
|
Kmods SIG |
d83023 |
+static struct ATTRIB *
|
|
Kmods SIG |
d83023 |
+ni_ins_new_attr(struct ntfs_inode *ni, struct mft_inode *mi,
|
|
Kmods SIG |
d83023 |
+ struct ATTR_LIST_ENTRY *le, enum ATTR_TYPE type,
|
|
Kmods SIG |
d83023 |
+ const __le16 *name, u8 name_len, u32 asize, u16 name_off,
|
|
Kmods SIG |
d83023 |
+ CLST svcn, struct ATTR_LIST_ENTRY **ins_le)
|
|
Kmods SIG |
d83023 |
{
|
|
Kmods SIG |
d83023 |
int err;
|
|
Kmods SIG |
d83023 |
struct ATTRIB *attr;
|
|
Kmods SIG |
d83023 |
@@ -507,6 +506,8 @@ static struct ATTRIB *ni_ins_new_attr(struct ntfs_inode *ni,
|
|
Kmods SIG |
d83023 |
le->ref = ref;
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
out:
|
|
Kmods SIG |
d83023 |
+ if (ins_le)
|
|
Kmods SIG |
d83023 |
+ *ins_le = le;
|
|
Kmods SIG |
d83023 |
return attr;
|
|
Kmods SIG |
d83023 |
}
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
@@ -599,7 +600,7 @@ static int ni_repack(struct ntfs_inode *ni)
|
|
Kmods SIG |
d83023 |
if (next_svcn >= evcn + 1) {
|
|
Kmods SIG |
d83023 |
/* We can remove this attribute segment. */
|
|
Kmods SIG |
d83023 |
al_remove_le(ni, le);
|
|
Kmods SIG |
d83023 |
- mi_remove_attr(mi, attr);
|
|
Kmods SIG |
d83023 |
+ mi_remove_attr(NULL, mi, attr);
|
|
Kmods SIG |
d83023 |
le = le_p;
|
|
Kmods SIG |
d83023 |
continue;
|
|
Kmods SIG |
d83023 |
}
|
|
Kmods SIG |
d83023 |
@@ -695,8 +696,8 @@ static int ni_try_remove_attr_list(struct ntfs_inode *ni)
|
|
Kmods SIG |
d83023 |
free -= asize;
|
|
Kmods SIG |
d83023 |
}
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
- /* Is seems that attribute list can be removed from primary record. */
|
|
Kmods SIG |
d83023 |
- mi_remove_attr(&ni->mi, attr_list);
|
|
Kmods SIG |
d83023 |
+ /* It seems that attribute list can be removed from primary record. */
|
|
Kmods SIG |
d83023 |
+ mi_remove_attr(NULL, &ni->mi, attr_list);
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
/*
|
|
Kmods SIG |
d83023 |
* Repeat the cycle above and move all attributes to primary record.
|
|
Kmods SIG |
d83023 |
@@ -724,7 +725,7 @@ static int ni_try_remove_attr_list(struct ntfs_inode *ni)
|
|
Kmods SIG |
d83023 |
attr_ins->id = id;
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
/* Remove from original record. */
|
|
Kmods SIG |
d83023 |
- mi_remove_attr(mi, attr);
|
|
Kmods SIG |
d83023 |
+ mi_remove_attr(NULL, mi, attr);
|
|
Kmods SIG |
d83023 |
}
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
run_deallocate(sbi, &ni->attr_list.run, true);
|
|
Kmods SIG |
d83023 |
@@ -842,7 +843,8 @@ int ni_create_attr_list(struct ntfs_inode *ni)
|
|
Kmods SIG |
d83023 |
memcpy(attr, b, asize);
|
|
Kmods SIG |
d83023 |
attr->id = le_b[nb]->id;
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
- WARN_ON(!mi_remove_attr(&ni->mi, b));
|
|
Kmods SIG |
d83023 |
+ /* Remove from primary record. */
|
|
Kmods SIG |
d83023 |
+ WARN_ON(!mi_remove_attr(NULL, &ni->mi, b));
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
if (to_free <= asize)
|
|
Kmods SIG |
d83023 |
break;
|
|
Kmods SIG |
d83023 |
@@ -883,7 +885,8 @@ int ni_create_attr_list(struct ntfs_inode *ni)
|
|
Kmods SIG |
d83023 |
static int ni_ins_attr_ext(struct ntfs_inode *ni, struct ATTR_LIST_ENTRY *le,
|
|
Kmods SIG |
d83023 |
enum ATTR_TYPE type, const __le16 *name, u8 name_len,
|
|
Kmods SIG |
d83023 |
u32 asize, CLST svcn, u16 name_off, bool force_ext,
|
|
Kmods SIG |
d83023 |
- struct ATTRIB **ins_attr, struct mft_inode **ins_mi)
|
|
Kmods SIG |
d83023 |
+ struct ATTRIB **ins_attr, struct mft_inode **ins_mi,
|
|
Kmods SIG |
d83023 |
+ struct ATTR_LIST_ENTRY **ins_le)
|
|
Kmods SIG |
d83023 |
{
|
|
Kmods SIG |
d83023 |
struct ATTRIB *attr;
|
|
Kmods SIG |
d83023 |
struct mft_inode *mi;
|
|
Kmods SIG |
d83023 |
@@ -956,12 +959,14 @@ static int ni_ins_attr_ext(struct ntfs_inode *ni, struct ATTR_LIST_ENTRY *le,
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
/* Try to insert attribute into this subrecord. */
|
|
Kmods SIG |
d83023 |
attr = ni_ins_new_attr(ni, mi, le, type, name, name_len, asize,
|
|
Kmods SIG |
d83023 |
- name_off, svcn);
|
|
Kmods SIG |
d83023 |
+ name_off, svcn, ins_le);
|
|
Kmods SIG |
d83023 |
if (!attr)
|
|
Kmods SIG |
d83023 |
continue;
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
if (ins_attr)
|
|
Kmods SIG |
d83023 |
*ins_attr = attr;
|
|
Kmods SIG |
d83023 |
+ if (ins_mi)
|
|
Kmods SIG |
d83023 |
+ *ins_mi = mi;
|
|
Kmods SIG |
d83023 |
return 0;
|
|
Kmods SIG |
d83023 |
}
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
@@ -977,7 +982,7 @@ static int ni_ins_attr_ext(struct ntfs_inode *ni, struct ATTR_LIST_ENTRY *le,
|
|
Kmods SIG |
d83023 |
}
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
attr = ni_ins_new_attr(ni, mi, le, type, name, name_len, asize,
|
|
Kmods SIG |
d83023 |
- name_off, svcn);
|
|
Kmods SIG |
d83023 |
+ name_off, svcn, ins_le);
|
|
Kmods SIG |
d83023 |
if (!attr)
|
|
Kmods SIG |
d83023 |
goto out2;
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
@@ -1016,7 +1021,8 @@ static int ni_ins_attr_ext(struct ntfs_inode *ni, struct ATTR_LIST_ENTRY *le,
|
|
Kmods SIG |
d83023 |
static int ni_insert_attr(struct ntfs_inode *ni, enum ATTR_TYPE type,
|
|
Kmods SIG |
d83023 |
const __le16 *name, u8 name_len, u32 asize,
|
|
Kmods SIG |
d83023 |
u16 name_off, CLST svcn, struct ATTRIB **ins_attr,
|
|
Kmods SIG |
d83023 |
- struct mft_inode **ins_mi)
|
|
Kmods SIG |
d83023 |
+ struct mft_inode **ins_mi,
|
|
Kmods SIG |
d83023 |
+ struct ATTR_LIST_ENTRY **ins_le)
|
|
Kmods SIG |
d83023 |
{
|
|
Kmods SIG |
d83023 |
struct ntfs_sb_info *sbi = ni->mi.sbi;
|
|
Kmods SIG |
d83023 |
int err;
|
|
Kmods SIG |
d83023 |
@@ -1045,7 +1051,7 @@ static int ni_insert_attr(struct ntfs_inode *ni, enum ATTR_TYPE type,
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
if (asize <= free) {
|
|
Kmods SIG |
d83023 |
attr = ni_ins_new_attr(ni, &ni->mi, NULL, type, name, name_len,
|
|
Kmods SIG |
d83023 |
- asize, name_off, svcn);
|
|
Kmods SIG |
d83023 |
+ asize, name_off, svcn, ins_le);
|
|
Kmods SIG |
d83023 |
if (attr) {
|
|
Kmods SIG |
d83023 |
if (ins_attr)
|
|
Kmods SIG |
d83023 |
*ins_attr = attr;
|
|
Kmods SIG |
d83023 |
@@ -1059,7 +1065,8 @@ static int ni_insert_attr(struct ntfs_inode *ni, enum ATTR_TYPE type,
|
|
Kmods SIG |
d83023 |
if (!is_mft || type != ATTR_DATA || svcn) {
|
|
Kmods SIG |
d83023 |
/* This ATTRIB will be external. */
|
|
Kmods SIG |
d83023 |
err = ni_ins_attr_ext(ni, NULL, type, name, name_len, asize,
|
|
Kmods SIG |
d83023 |
- svcn, name_off, false, ins_attr, ins_mi);
|
|
Kmods SIG |
d83023 |
+ svcn, name_off, false, ins_attr, ins_mi,
|
|
Kmods SIG |
d83023 |
+ ins_le);
|
|
Kmods SIG |
d83023 |
goto out;
|
|
Kmods SIG |
d83023 |
}
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
@@ -1117,7 +1124,7 @@ static int ni_insert_attr(struct ntfs_inode *ni, enum ATTR_TYPE type,
|
|
Kmods SIG |
d83023 |
t16 = le16_to_cpu(attr->name_off);
|
|
Kmods SIG |
d83023 |
err = ni_ins_attr_ext(ni, le, attr->type, Add2Ptr(attr, t16),
|
|
Kmods SIG |
d83023 |
attr->name_len, t32, attr_svcn(attr), t16,
|
|
Kmods SIG |
d83023 |
- false, &eattr, NULL);
|
|
Kmods SIG |
d83023 |
+ false, &eattr, NULL, NULL);
|
|
Kmods SIG |
d83023 |
if (err)
|
|
Kmods SIG |
d83023 |
return err;
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
@@ -1125,8 +1132,8 @@ static int ni_insert_attr(struct ntfs_inode *ni, enum ATTR_TYPE type,
|
|
Kmods SIG |
d83023 |
memcpy(eattr, attr, t32);
|
|
Kmods SIG |
d83023 |
eattr->id = id;
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
- /* Remove attrib from primary record. */
|
|
Kmods SIG |
d83023 |
- mi_remove_attr(&ni->mi, attr);
|
|
Kmods SIG |
d83023 |
+ /* Remove from primary record. */
|
|
Kmods SIG |
d83023 |
+ mi_remove_attr(NULL, &ni->mi, attr);
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
/* attr now points to next attribute. */
|
|
Kmods SIG |
d83023 |
if (attr->type == ATTR_END)
|
|
Kmods SIG |
d83023 |
@@ -1136,7 +1143,7 @@ static int ni_insert_attr(struct ntfs_inode *ni, enum ATTR_TYPE type,
|
|
Kmods SIG |
d83023 |
;
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
attr = ni_ins_new_attr(ni, &ni->mi, NULL, type, name, name_len, asize,
|
|
Kmods SIG |
d83023 |
- name_off, svcn);
|
|
Kmods SIG |
d83023 |
+ name_off, svcn, ins_le);
|
|
Kmods SIG |
d83023 |
if (!attr) {
|
|
Kmods SIG |
d83023 |
err = -EINVAL;
|
|
Kmods SIG |
d83023 |
goto out;
|
|
Kmods SIG |
d83023 |
@@ -1251,7 +1258,7 @@ static int ni_expand_mft_list(struct ntfs_inode *ni)
|
|
Kmods SIG |
d83023 |
*/
|
|
Kmods SIG |
d83023 |
attr = ni_ins_new_attr(ni, mi_min, NULL, ATTR_DATA, NULL, 0,
|
|
Kmods SIG |
d83023 |
SIZEOF_NONRESIDENT + run_size,
|
|
Kmods SIG |
d83023 |
- SIZEOF_NONRESIDENT, svcn);
|
|
Kmods SIG |
d83023 |
+ SIZEOF_NONRESIDENT, svcn, NULL);
|
|
Kmods SIG |
d83023 |
if (!attr) {
|
|
Kmods SIG |
d83023 |
err = -EINVAL;
|
|
Kmods SIG |
d83023 |
goto out;
|
|
Kmods SIG |
d83023 |
@@ -1315,14 +1322,15 @@ int ni_expand_list(struct ntfs_inode *ni)
|
|
Kmods SIG |
d83023 |
err = ni_ins_attr_ext(ni, le, attr->type, attr_name(attr),
|
|
Kmods SIG |
d83023 |
attr->name_len, asize, attr_svcn(attr),
|
|
Kmods SIG |
d83023 |
le16_to_cpu(attr->name_off), true,
|
|
Kmods SIG |
d83023 |
- &ins_attr, NULL);
|
|
Kmods SIG |
d83023 |
+ &ins_attr, NULL, NULL);
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
if (err)
|
|
Kmods SIG |
d83023 |
goto out;
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
memcpy(ins_attr, attr, asize);
|
|
Kmods SIG |
d83023 |
ins_attr->id = le->id;
|
|
Kmods SIG |
d83023 |
- mi_remove_attr(&ni->mi, attr);
|
|
Kmods SIG |
d83023 |
+ /* Remove from primary record. */
|
|
Kmods SIG |
d83023 |
+ mi_remove_attr(NULL, &ni->mi, attr);
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
done += asize;
|
|
Kmods SIG |
d83023 |
goto out;
|
|
Kmods SIG |
d83023 |
@@ -1382,7 +1390,7 @@ int ni_insert_nonresident(struct ntfs_inode *ni, enum ATTR_TYPE type,
|
|
Kmods SIG |
d83023 |
}
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
err = ni_insert_attr(ni, type, name, name_len, asize, name_off, svcn,
|
|
Kmods SIG |
d83023 |
- &attr, mi);
|
|
Kmods SIG |
d83023 |
+ &attr, mi, NULL);
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
if (err)
|
|
Kmods SIG |
d83023 |
goto out;
|
|
Kmods SIG |
d83023 |
@@ -1422,7 +1430,8 @@ int ni_insert_nonresident(struct ntfs_inode *ni, enum ATTR_TYPE type,
|
|
Kmods SIG |
d83023 |
*/
|
|
Kmods SIG |
d83023 |
int ni_insert_resident(struct ntfs_inode *ni, u32 data_size,
|
|
Kmods SIG |
d83023 |
enum ATTR_TYPE type, const __le16 *name, u8 name_len,
|
|
Kmods SIG |
d83023 |
- struct ATTRIB **new_attr, struct mft_inode **mi)
|
|
Kmods SIG |
d83023 |
+ struct ATTRIB **new_attr, struct mft_inode **mi,
|
|
Kmods SIG |
d83023 |
+ struct ATTR_LIST_ENTRY **le)
|
|
Kmods SIG |
d83023 |
{
|
|
Kmods SIG |
d83023 |
int err;
|
|
Kmods SIG |
d83023 |
u32 name_size = ALIGN(name_len * sizeof(short), 8);
|
|
Kmods SIG |
d83023 |
@@ -1430,7 +1439,7 @@ int ni_insert_resident(struct ntfs_inode *ni, u32 data_size,
|
|
Kmods SIG |
d83023 |
struct ATTRIB *attr;
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
err = ni_insert_attr(ni, type, name, name_len, asize, SIZEOF_RESIDENT,
|
|
Kmods SIG |
d83023 |
- 0, &attr, mi);
|
|
Kmods SIG |
d83023 |
+ 0, &attr, mi, le);
|
|
Kmods SIG |
d83023 |
if (err)
|
|
Kmods SIG |
d83023 |
return err;
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
@@ -1439,8 +1448,13 @@ int ni_insert_resident(struct ntfs_inode *ni, u32 data_size,
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
attr->res.data_size = cpu_to_le32(data_size);
|
|
Kmods SIG |
d83023 |
attr->res.data_off = cpu_to_le16(SIZEOF_RESIDENT + name_size);
|
|
Kmods SIG |
d83023 |
- if (type == ATTR_NAME)
|
|
Kmods SIG |
d83023 |
+ if (type == ATTR_NAME) {
|
|
Kmods SIG |
d83023 |
attr->res.flags = RESIDENT_FLAG_INDEXED;
|
|
Kmods SIG |
d83023 |
+
|
|
Kmods SIG |
d83023 |
+ /* is_attr_indexed(attr)) == true */
|
|
Kmods SIG |
d83023 |
+ le16_add_cpu(&ni->mi.mrec->hard_links, +1);
|
|
Kmods SIG |
d83023 |
+ ni->mi.dirty = true;
|
|
Kmods SIG |
d83023 |
+ }
|
|
Kmods SIG |
d83023 |
attr->res.res = 0;
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
if (new_attr)
|
|
Kmods SIG |
d83023 |
@@ -1452,22 +1466,13 @@ int ni_insert_resident(struct ntfs_inode *ni, u32 data_size,
|
|
Kmods SIG |
d83023 |
/*
|
|
Kmods SIG |
d83023 |
* ni_remove_attr_le - Remove attribute from record.
|
|
Kmods SIG |
d83023 |
*/
|
|
Kmods SIG |
d83023 |
-int ni_remove_attr_le(struct ntfs_inode *ni, struct ATTRIB *attr,
|
|
Kmods SIG |
d83023 |
- struct ATTR_LIST_ENTRY *le)
|
|
Kmods SIG |
d83023 |
+void ni_remove_attr_le(struct ntfs_inode *ni, struct ATTRIB *attr,
|
|
Kmods SIG |
d83023 |
+ struct mft_inode *mi, struct ATTR_LIST_ENTRY *le)
|
|
Kmods SIG |
d83023 |
{
|
|
Kmods SIG |
d83023 |
- int err;
|
|
Kmods SIG |
d83023 |
- struct mft_inode *mi;
|
|
Kmods SIG |
d83023 |
-
|
|
Kmods SIG |
d83023 |
- err = ni_load_mi(ni, le, &mi);
|
|
Kmods SIG |
d83023 |
- if (err)
|
|
Kmods SIG |
d83023 |
- return err;
|
|
Kmods SIG |
d83023 |
-
|
|
Kmods SIG |
d83023 |
- mi_remove_attr(mi, attr);
|
|
Kmods SIG |
d83023 |
+ mi_remove_attr(ni, mi, attr);
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
if (le)
|
|
Kmods SIG |
d83023 |
al_remove_le(ni, le);
|
|
Kmods SIG |
d83023 |
-
|
|
Kmods SIG |
d83023 |
- return 0;
|
|
Kmods SIG |
d83023 |
}
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
/*
|
|
Kmods SIG |
d83023 |
@@ -1549,10 +1554,12 @@ int ni_delete_all(struct ntfs_inode *ni)
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
/* ni_fname_name
|
|
Kmods SIG |
d83023 |
*
|
|
Kmods SIG |
d83023 |
- *Return: File name attribute by its value. */
|
|
Kmods SIG |
d83023 |
+ * Return: File name attribute by its value.
|
|
Kmods SIG |
d83023 |
+ */
|
|
Kmods SIG |
d83023 |
struct ATTR_FILE_NAME *ni_fname_name(struct ntfs_inode *ni,
|
|
Kmods SIG |
d83023 |
const struct cpu_str *uni,
|
|
Kmods SIG |
d83023 |
const struct MFT_REF *home_dir,
|
|
Kmods SIG |
d83023 |
+ struct mft_inode **mi,
|
|
Kmods SIG |
d83023 |
struct ATTR_LIST_ENTRY **le)
|
|
Kmods SIG |
d83023 |
{
|
|
Kmods SIG |
d83023 |
struct ATTRIB *attr = NULL;
|
|
Kmods SIG |
d83023 |
@@ -1562,7 +1569,7 @@ struct ATTR_FILE_NAME *ni_fname_name(struct ntfs_inode *ni,
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
/* Enumerate all names. */
|
|
Kmods SIG |
d83023 |
next:
|
|
Kmods SIG |
d83023 |
- attr = ni_find_attr(ni, attr, le, ATTR_NAME, NULL, 0, NULL, NULL);
|
|
Kmods SIG |
d83023 |
+ attr = ni_find_attr(ni, attr, le, ATTR_NAME, NULL, 0, NULL, mi);
|
|
Kmods SIG |
d83023 |
if (!attr)
|
|
Kmods SIG |
d83023 |
return NULL;
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
@@ -1592,6 +1599,7 @@ struct ATTR_FILE_NAME *ni_fname_name(struct ntfs_inode *ni,
|
|
Kmods SIG |
d83023 |
* Return: File name attribute with given type.
|
|
Kmods SIG |
d83023 |
*/
|
|
Kmods SIG |
d83023 |
struct ATTR_FILE_NAME *ni_fname_type(struct ntfs_inode *ni, u8 name_type,
|
|
Kmods SIG |
d83023 |
+ struct mft_inode **mi,
|
|
Kmods SIG |
d83023 |
struct ATTR_LIST_ENTRY **le)
|
|
Kmods SIG |
d83023 |
{
|
|
Kmods SIG |
d83023 |
struct ATTRIB *attr = NULL;
|
|
Kmods SIG |
d83023 |
@@ -1599,10 +1607,12 @@ struct ATTR_FILE_NAME *ni_fname_type(struct ntfs_inode *ni, u8 name_type,
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
*le = NULL;
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
+ if (FILE_NAME_POSIX == name_type)
|
|
Kmods SIG |
d83023 |
+ return NULL;
|
|
Kmods SIG |
d83023 |
+
|
|
Kmods SIG |
d83023 |
/* Enumerate all names. */
|
|
Kmods SIG |
d83023 |
for (;;) {
|
|
Kmods SIG |
d83023 |
- attr = ni_find_attr(ni, attr, le, ATTR_NAME, NULL, 0, NULL,
|
|
Kmods SIG |
d83023 |
- NULL);
|
|
Kmods SIG |
d83023 |
+ attr = ni_find_attr(ni, attr, le, ATTR_NAME, NULL, 0, NULL, mi);
|
|
Kmods SIG |
d83023 |
if (!attr)
|
|
Kmods SIG |
d83023 |
return NULL;
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
@@ -2788,6 +2798,222 @@ int ni_write_frame(struct ntfs_inode *ni, struct page **pages,
|
|
Kmods SIG |
d83023 |
return err;
|
|
Kmods SIG |
d83023 |
}
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
+/*
|
|
Kmods SIG |
d83023 |
+ * ni_remove_name - Removes name 'de' from MFT and from directory.
|
|
Kmods SIG |
d83023 |
+ * 'de2' and 'undo_step' are used to restore MFT/dir, if error occurs.
|
|
Kmods SIG |
d83023 |
+ */
|
|
Kmods SIG |
d83023 |
+int ni_remove_name(struct ntfs_inode *dir_ni, struct ntfs_inode *ni,
|
|
Kmods SIG |
d83023 |
+ struct NTFS_DE *de, struct NTFS_DE **de2, int *undo_step)
|
|
Kmods SIG |
d83023 |
+{
|
|
Kmods SIG |
d83023 |
+ int err;
|
|
Kmods SIG |
d83023 |
+ struct ntfs_sb_info *sbi = ni->mi.sbi;
|
|
Kmods SIG |
d83023 |
+ struct ATTR_FILE_NAME *de_name = (struct ATTR_FILE_NAME *)(de + 1);
|
|
Kmods SIG |
d83023 |
+ struct ATTR_FILE_NAME *fname;
|
|
Kmods SIG |
d83023 |
+ struct ATTR_LIST_ENTRY *le;
|
|
Kmods SIG |
d83023 |
+ struct mft_inode *mi;
|
|
Kmods SIG |
d83023 |
+ u16 de_key_size = le16_to_cpu(de->key_size);
|
|
Kmods SIG |
d83023 |
+ u8 name_type;
|
|
Kmods SIG |
d83023 |
+
|
|
Kmods SIG |
d83023 |
+ *undo_step = 0;
|
|
Kmods SIG |
d83023 |
+
|
|
Kmods SIG |
d83023 |
+ /* Find name in record. */
|
|
Kmods SIG |
d83023 |
+ mi_get_ref(&dir_ni->mi, &de_name->home);
|
|
Kmods SIG |
d83023 |
+
|
|
Kmods SIG |
d83023 |
+ fname = ni_fname_name(ni, (struct cpu_str *)&de_name->name_len,
|
|
Kmods SIG |
d83023 |
+ &de_name->home, &mi, &le);
|
|
Kmods SIG |
d83023 |
+ if (!fname)
|
|
Kmods SIG |
d83023 |
+ return -ENOENT;
|
|
Kmods SIG |
d83023 |
+
|
|
Kmods SIG |
d83023 |
+ memcpy(&de_name->dup, &fname->dup, sizeof(struct NTFS_DUP_INFO));
|
|
Kmods SIG |
d83023 |
+ name_type = paired_name(fname->type);
|
|
Kmods SIG |
d83023 |
+
|
|
Kmods SIG |
d83023 |
+ /* Mark ntfs as dirty. It will be cleared at umount. */
|
|
Kmods SIG |
d83023 |
+ ntfs_set_state(sbi, NTFS_DIRTY_DIRTY);
|
|
Kmods SIG |
d83023 |
+
|
|
Kmods SIG |
d83023 |
+ /* Step 1: Remove name from directory. */
|
|
Kmods SIG |
d83023 |
+ err = indx_delete_entry(&dir_ni->dir, dir_ni, fname, de_key_size, sbi);
|
|
Kmods SIG |
d83023 |
+ if (err)
|
|
Kmods SIG |
d83023 |
+ return err;
|
|
Kmods SIG |
d83023 |
+
|
|
Kmods SIG |
d83023 |
+ /* Step 2: Remove name from MFT. */
|
|
Kmods SIG |
d83023 |
+ ni_remove_attr_le(ni, attr_from_name(fname), mi, le);
|
|
Kmods SIG |
d83023 |
+
|
|
Kmods SIG |
d83023 |
+ *undo_step = 2;
|
|
Kmods SIG |
d83023 |
+
|
|
Kmods SIG |
d83023 |
+ /* Get paired name. */
|
|
Kmods SIG |
d83023 |
+ fname = ni_fname_type(ni, name_type, &mi, &le);
|
|
Kmods SIG |
d83023 |
+ if (fname) {
|
|
Kmods SIG |
d83023 |
+ u16 de2_key_size = fname_full_size(fname);
|
|
Kmods SIG |
d83023 |
+
|
|
Kmods SIG |
d83023 |
+ *de2 = Add2Ptr(de, 1024);
|
|
Kmods SIG |
d83023 |
+ (*de2)->key_size = cpu_to_le16(de2_key_size);
|
|
Kmods SIG |
d83023 |
+
|
|
Kmods SIG |
d83023 |
+ memcpy(*de2 + 1, fname, de2_key_size);
|
|
Kmods SIG |
d83023 |
+
|
|
Kmods SIG |
d83023 |
+ /* Step 3: Remove paired name from directory. */
|
|
Kmods SIG |
d83023 |
+ err = indx_delete_entry(&dir_ni->dir, dir_ni, fname,
|
|
Kmods SIG |
d83023 |
+ de2_key_size, sbi);
|
|
Kmods SIG |
d83023 |
+ if (err)
|
|
Kmods SIG |
d83023 |
+ return err;
|
|
Kmods SIG |
d83023 |
+
|
|
Kmods SIG |
d83023 |
+ /* Step 4: Remove paired name from MFT. */
|
|
Kmods SIG |
d83023 |
+ ni_remove_attr_le(ni, attr_from_name(fname), mi, le);
|
|
Kmods SIG |
d83023 |
+
|
|
Kmods SIG |
d83023 |
+ *undo_step = 4;
|
|
Kmods SIG |
d83023 |
+ }
|
|
Kmods SIG |
d83023 |
+ return 0;
|
|
Kmods SIG |
d83023 |
+}
|
|
Kmods SIG |
d83023 |
+
|
|
Kmods SIG |
d83023 |
+/*
|
|
Kmods SIG |
d83023 |
+ * ni_remove_name_undo - Paired function for ni_remove_name.
|
|
Kmods SIG |
d83023 |
+ *
|
|
Kmods SIG |
d83023 |
+ * Return: True if ok
|
|
Kmods SIG |
d83023 |
+ */
|
|
Kmods SIG |
d83023 |
+bool ni_remove_name_undo(struct ntfs_inode *dir_ni, struct ntfs_inode *ni,
|
|
Kmods SIG |
d83023 |
+ struct NTFS_DE *de, struct NTFS_DE *de2, int undo_step)
|
|
Kmods SIG |
d83023 |
+{
|
|
Kmods SIG |
d83023 |
+ struct ntfs_sb_info *sbi = ni->mi.sbi;
|
|
Kmods SIG |
d83023 |
+ struct ATTRIB *attr;
|
|
Kmods SIG |
d83023 |
+ u16 de_key_size = de2 ? le16_to_cpu(de2->key_size) : 0;
|
|
Kmods SIG |
d83023 |
+
|
|
Kmods SIG |
d83023 |
+ switch (undo_step) {
|
|
Kmods SIG |
d83023 |
+ case 4:
|
|
Kmods SIG |
d83023 |
+ if (ni_insert_resident(ni, de_key_size, ATTR_NAME, NULL, 0,
|
|
Kmods SIG |
d83023 |
+ &attr, NULL, NULL)) {
|
|
Kmods SIG |
d83023 |
+ return false;
|
|
Kmods SIG |
d83023 |
+ }
|
|
Kmods SIG |
d83023 |
+ memcpy(Add2Ptr(attr, SIZEOF_RESIDENT), de2 + 1, de_key_size);
|
|
Kmods SIG |
d83023 |
+
|
|
Kmods SIG |
d83023 |
+ mi_get_ref(&ni->mi, &de2->ref);
|
|
Kmods SIG |
d83023 |
+ de2->size = cpu_to_le16(ALIGN(de_key_size, 8) +
|
|
Kmods SIG |
d83023 |
+ sizeof(struct NTFS_DE));
|
|
Kmods SIG |
d83023 |
+ de2->flags = 0;
|
|
Kmods SIG |
d83023 |
+ de2->res = 0;
|
|
Kmods SIG |
d83023 |
+
|
|
Kmods SIG |
d83023 |
+ if (indx_insert_entry(&dir_ni->dir, dir_ni, de2, sbi, NULL,
|
|
Kmods SIG |
d83023 |
+ 1)) {
|
|
Kmods SIG |
d83023 |
+ return false;
|
|
Kmods SIG |
d83023 |
+ }
|
|
Kmods SIG |
d83023 |
+ fallthrough;
|
|
Kmods SIG |
d83023 |
+
|
|
Kmods SIG |
d83023 |
+ case 2:
|
|
Kmods SIG |
d83023 |
+ de_key_size = le16_to_cpu(de->key_size);
|
|
Kmods SIG |
d83023 |
+
|
|
Kmods SIG |
d83023 |
+ if (ni_insert_resident(ni, de_key_size, ATTR_NAME, NULL, 0,
|
|
Kmods SIG |
d83023 |
+ &attr, NULL, NULL)) {
|
|
Kmods SIG |
d83023 |
+ return false;
|
|
Kmods SIG |
d83023 |
+ }
|
|
Kmods SIG |
d83023 |
+
|
|
Kmods SIG |
d83023 |
+ memcpy(Add2Ptr(attr, SIZEOF_RESIDENT), de + 1, de_key_size);
|
|
Kmods SIG |
d83023 |
+ mi_get_ref(&ni->mi, &de->ref);
|
|
Kmods SIG |
d83023 |
+
|
|
Kmods SIG |
d83023 |
+ if (indx_insert_entry(&dir_ni->dir, dir_ni, de, sbi, NULL, 1)) {
|
|
Kmods SIG |
d83023 |
+ return false;
|
|
Kmods SIG |
d83023 |
+ }
|
|
Kmods SIG |
d83023 |
+ }
|
|
Kmods SIG |
d83023 |
+
|
|
Kmods SIG |
d83023 |
+ return true;
|
|
Kmods SIG |
d83023 |
+}
|
|
Kmods SIG |
d83023 |
+
|
|
Kmods SIG |
d83023 |
+/*
|
|
Kmods SIG |
d83023 |
+ * ni_add_name - Add new name in MFT and in directory.
|
|
Kmods SIG |
d83023 |
+ */
|
|
Kmods SIG |
d83023 |
+int ni_add_name(struct ntfs_inode *dir_ni, struct ntfs_inode *ni,
|
|
Kmods SIG |
d83023 |
+ struct NTFS_DE *de)
|
|
Kmods SIG |
d83023 |
+{
|
|
Kmods SIG |
d83023 |
+ int err;
|
|
Kmods SIG |
d83023 |
+ struct ATTRIB *attr;
|
|
Kmods SIG |
d83023 |
+ struct ATTR_LIST_ENTRY *le;
|
|
Kmods SIG |
d83023 |
+ struct mft_inode *mi;
|
|
Kmods SIG |
d83023 |
+ struct ATTR_FILE_NAME *de_name = (struct ATTR_FILE_NAME *)(de + 1);
|
|
Kmods SIG |
d83023 |
+ u16 de_key_size = le16_to_cpu(de->key_size);
|
|
Kmods SIG |
d83023 |
+
|
|
Kmods SIG |
d83023 |
+ mi_get_ref(&ni->mi, &de->ref);
|
|
Kmods SIG |
d83023 |
+ mi_get_ref(&dir_ni->mi, &de_name->home);
|
|
Kmods SIG |
d83023 |
+
|
|
Kmods SIG |
d83023 |
+ /* Insert new name in MFT. */
|
|
Kmods SIG |
d83023 |
+ err = ni_insert_resident(ni, de_key_size, ATTR_NAME, NULL, 0, &attr,
|
|
Kmods SIG |
d83023 |
+ &mi, &le);
|
|
Kmods SIG |
d83023 |
+ if (err)
|
|
Kmods SIG |
d83023 |
+ return err;
|
|
Kmods SIG |
d83023 |
+
|
|
Kmods SIG |
d83023 |
+ memcpy(Add2Ptr(attr, SIZEOF_RESIDENT), de_name, de_key_size);
|
|
Kmods SIG |
d83023 |
+
|
|
Kmods SIG |
d83023 |
+ /* Insert new name in directory. */
|
|
Kmods SIG |
d83023 |
+ err = indx_insert_entry(&dir_ni->dir, dir_ni, de, ni->mi.sbi, NULL, 0);
|
|
Kmods SIG |
d83023 |
+ if (err)
|
|
Kmods SIG |
d83023 |
+ ni_remove_attr_le(ni, attr, mi, le);
|
|
Kmods SIG |
d83023 |
+
|
|
Kmods SIG |
d83023 |
+ return err;
|
|
Kmods SIG |
d83023 |
+}
|
|
Kmods SIG |
d83023 |
+
|
|
Kmods SIG |
d83023 |
+/*
|
|
Kmods SIG |
d83023 |
+ * ni_rename - Remove one name and insert new name.
|
|
Kmods SIG |
d83023 |
+ */
|
|
Kmods SIG |
d83023 |
+int ni_rename(struct ntfs_inode *dir_ni, struct ntfs_inode *new_dir_ni,
|
|
Kmods SIG |
d83023 |
+ struct ntfs_inode *ni, struct NTFS_DE *de, struct NTFS_DE *new_de,
|
|
Kmods SIG |
d83023 |
+ bool *is_bad)
|
|
Kmods SIG |
d83023 |
+{
|
|
Kmods SIG |
d83023 |
+ int err;
|
|
Kmods SIG |
d83023 |
+ struct NTFS_DE *de2 = NULL;
|
|
Kmods SIG |
d83023 |
+ int undo = 0;
|
|
Kmods SIG |
d83023 |
+
|
|
Kmods SIG |
d83023 |
+ /*
|
|
Kmods SIG |
d83023 |
+ * There are two possible ways to rename:
|
|
Kmods SIG |
d83023 |
+ * 1) Add new name and remove old name.
|
|
Kmods SIG |
d83023 |
+ * 2) Remove old name and add new name.
|
|
Kmods SIG |
d83023 |
+ *
|
|
Kmods SIG |
d83023 |
+ * In most cases (not all!) adding new name in MFT and in directory can
|
|
Kmods SIG |
d83023 |
+ * allocate additional cluster(s).
|
|
Kmods SIG |
d83023 |
+ * Second way may result to bad inode if we can't add new name
|
|
Kmods SIG |
d83023 |
+ * and then can't restore (add) old name.
|
|
Kmods SIG |
d83023 |
+ */
|
|
Kmods SIG |
d83023 |
+
|
|
Kmods SIG |
d83023 |
+ /*
|
|
Kmods SIG |
d83023 |
+ * Way 1 - Add new + remove old.
|
|
Kmods SIG |
d83023 |
+ */
|
|
Kmods SIG |
d83023 |
+ err = ni_add_name(new_dir_ni, ni, new_de);
|
|
Kmods SIG |
d83023 |
+ if (!err) {
|
|
Kmods SIG |
d83023 |
+ err = ni_remove_name(dir_ni, ni, de, &de2, &undo);
|
|
Kmods SIG |
d83023 |
+ if (err && ni_remove_name(new_dir_ni, ni, new_de, &de2, &undo))
|
|
Kmods SIG |
d83023 |
+ *is_bad = true;
|
|
Kmods SIG |
d83023 |
+ }
|
|
Kmods SIG |
d83023 |
+
|
|
Kmods SIG |
d83023 |
+ /*
|
|
Kmods SIG |
d83023 |
+ * Way 2 - Remove old + add new.
|
|
Kmods SIG |
d83023 |
+ */
|
|
Kmods SIG |
d83023 |
+ /*
|
|
Kmods SIG |
d83023 |
+ * err = ni_remove_name(dir_ni, ni, de, &de2, &undo);
|
|
Kmods SIG |
d83023 |
+ * if (!err) {
|
|
Kmods SIG |
d83023 |
+ * err = ni_add_name(new_dir_ni, ni, new_de);
|
|
Kmods SIG |
d83023 |
+ * if (err && !ni_remove_name_undo(dir_ni, ni, de, de2, undo))
|
|
Kmods SIG |
d83023 |
+ * *is_bad = true;
|
|
Kmods SIG |
d83023 |
+ * }
|
|
Kmods SIG |
d83023 |
+ */
|
|
Kmods SIG |
d83023 |
+
|
|
Kmods SIG |
d83023 |
+ return err;
|
|
Kmods SIG |
d83023 |
+}
|
|
Kmods SIG |
d83023 |
+
|
|
Kmods SIG |
d83023 |
+/*
|
|
Kmods SIG |
d83023 |
+ * ni_is_dirty - Return: True if 'ni' requires ni_write_inode.
|
|
Kmods SIG |
d83023 |
+ */
|
|
Kmods SIG |
d83023 |
+bool ni_is_dirty(struct inode *inode)
|
|
Kmods SIG |
d83023 |
+{
|
|
Kmods SIG |
d83023 |
+ struct ntfs_inode *ni = ntfs_i(inode);
|
|
Kmods SIG |
d83023 |
+ struct rb_node *node;
|
|
Kmods SIG |
d83023 |
+
|
|
Kmods SIG |
d83023 |
+ if (ni->mi.dirty || ni->attr_list.dirty ||
|
|
Kmods SIG |
d83023 |
+ (ni->ni_flags & NI_FLAG_UPDATE_PARENT))
|
|
Kmods SIG |
d83023 |
+ return true;
|
|
Kmods SIG |
d83023 |
+
|
|
Kmods SIG |
d83023 |
+ for (node = rb_first(&ni->mi_tree); node; node = rb_next(node)) {
|
|
Kmods SIG |
d83023 |
+ if (rb_entry(node, struct mft_inode, node)->dirty)
|
|
Kmods SIG |
d83023 |
+ return true;
|
|
Kmods SIG |
d83023 |
+ }
|
|
Kmods SIG |
d83023 |
+
|
|
Kmods SIG |
d83023 |
+ return false;
|
|
Kmods SIG |
d83023 |
+}
|
|
Kmods SIG |
d83023 |
+
|
|
Kmods SIG |
d83023 |
/*
|
|
Kmods SIG |
d83023 |
* ni_update_parent
|
|
Kmods SIG |
d83023 |
*
|
|
Kmods SIG |
d83023 |
@@ -2802,8 +3028,6 @@ static bool ni_update_parent(struct ntfs_inode *ni, struct NTFS_DUP_INFO *dup,
|
|
Kmods SIG |
d83023 |
struct ntfs_sb_info *sbi = ni->mi.sbi;
|
|
Kmods SIG |
d83023 |
struct super_block *sb = sbi->sb;
|
|
Kmods SIG |
d83023 |
bool re_dirty = false;
|
|
Kmods SIG |
d83023 |
- bool active = sb->s_flags & SB_ACTIVE;
|
|
Kmods SIG |
d83023 |
- bool upd_parent = ni->ni_flags & NI_FLAG_UPDATE_PARENT;
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
if (ni->mi.mrec->flags & RECORD_FLAG_DIR) {
|
|
Kmods SIG |
d83023 |
dup->fa |= FILE_ATTRIBUTE_DIRECTORY;
|
|
Kmods SIG |
d83023 |
@@ -2867,19 +3091,9 @@ static bool ni_update_parent(struct ntfs_inode *ni, struct NTFS_DUP_INFO *dup,
|
|
Kmods SIG |
d83023 |
struct ATTR_FILE_NAME *fname;
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
fname = resident_data_ex(attr, SIZEOF_ATTRIBUTE_FILENAME);
|
|
Kmods SIG |
d83023 |
- if (!fname)
|
|
Kmods SIG |
d83023 |
+ if (!fname || !memcmp(&fname->dup, dup, sizeof(fname->dup)))
|
|
Kmods SIG |
d83023 |
continue;
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
- if (memcmp(&fname->dup, dup, sizeof(fname->dup))) {
|
|
Kmods SIG |
d83023 |
- memcpy(&fname->dup, dup, sizeof(fname->dup));
|
|
Kmods SIG |
d83023 |
- mi->dirty = true;
|
|
Kmods SIG |
d83023 |
- } else if (!upd_parent) {
|
|
Kmods SIG |
d83023 |
- continue;
|
|
Kmods SIG |
d83023 |
- }
|
|
Kmods SIG |
d83023 |
-
|
|
Kmods SIG |
d83023 |
- if (!active)
|
|
Kmods SIG |
d83023 |
- continue; /* Avoid __wait_on_freeing_inode(inode); */
|
|
Kmods SIG |
d83023 |
-
|
|
Kmods SIG |
d83023 |
/* ntfs_iget5 may sleep. */
|
|
Kmods SIG |
d83023 |
dir = ntfs_iget5(sb, &fname->home, NULL);
|
|
Kmods SIG |
d83023 |
if (IS_ERR(dir)) {
|
|
Kmods SIG |
d83023 |
@@ -2898,6 +3112,8 @@ static bool ni_update_parent(struct ntfs_inode *ni, struct NTFS_DUP_INFO *dup,
|
|
Kmods SIG |
d83023 |
} else {
|
|
Kmods SIG |
d83023 |
indx_update_dup(dir_ni, sbi, fname, dup, sync);
|
|
Kmods SIG |
d83023 |
ni_unlock(dir_ni);
|
|
Kmods SIG |
d83023 |
+ memcpy(&fname->dup, dup, sizeof(fname->dup));
|
|
Kmods SIG |
d83023 |
+ mi->dirty = true;
|
|
Kmods SIG |
d83023 |
}
|
|
Kmods SIG |
d83023 |
}
|
|
Kmods SIG |
d83023 |
iput(dir);
|
|
Kmods SIG |
d83023 |
@@ -2969,7 +3185,9 @@ int ni_write_inode(struct inode *inode, int sync, const char *hint)
|
|
Kmods SIG |
d83023 |
ni->mi.dirty = true;
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
if (!ntfs_is_meta_file(sbi, inode->i_ino) &&
|
|
Kmods SIG |
d83023 |
- (modified || (ni->ni_flags & NI_FLAG_UPDATE_PARENT))) {
|
|
Kmods SIG |
d83023 |
+ (modified || (ni->ni_flags & NI_FLAG_UPDATE_PARENT))
|
|
Kmods SIG |
d83023 |
+ /* Avoid __wait_on_freeing_inode(inode). */
|
|
Kmods SIG |
d83023 |
+ && (sb->s_flags & SB_ACTIVE)) {
|
|
Kmods SIG |
d83023 |
dup.cr_time = std->cr_time;
|
|
Kmods SIG |
d83023 |
/* Not critical if this function fail. */
|
|
Kmods SIG |
d83023 |
re_dirty = ni_update_parent(ni, &dup, sync);
|
|
Kmods SIG |
d83023 |
@@ -3033,7 +3251,7 @@ int ni_write_inode(struct inode *inode, int sync, const char *hint)
|
|
Kmods SIG |
d83023 |
return err;
|
|
Kmods SIG |
d83023 |
}
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
- if (re_dirty && (sb->s_flags & SB_ACTIVE))
|
|
Kmods SIG |
d83023 |
+ if (re_dirty)
|
|
Kmods SIG |
d83023 |
mark_inode_dirty_sync(inode);
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
return 0;
|
|
Kmods SIG |
d83023 |
diff --git a/src/fsntfs.c b/src/fsntfs.c
|
|
Kmods SIG |
d83023 |
index 0edb95ed9717f442f97b3ba3e85b4b6a361e0e27..66924943921771d3cf46f6a762b1ea81ae1e9ca2 100644
|
|
Kmods SIG |
d83023 |
--- a/src/fsntfs.c
|
|
Kmods SIG |
d83023 |
+++ b/src/fsntfs.c
|
|
Kmods SIG |
d83023 |
@@ -358,29 +358,25 @@ int ntfs_look_for_free_space(struct ntfs_sb_info *sbi, CLST lcn, CLST len,
|
|
Kmods SIG |
d83023 |
enum ALLOCATE_OPT opt)
|
|
Kmods SIG |
d83023 |
{
|
|
Kmods SIG |
d83023 |
int err;
|
|
Kmods SIG |
d83023 |
+ CLST alen = 0;
|
|
Kmods SIG |
d83023 |
struct super_block *sb = sbi->sb;
|
|
Kmods SIG |
d83023 |
- size_t a_lcn, zlen, zeroes, zlcn, zlen2, ztrim, new_zlen;
|
|
Kmods SIG |
d83023 |
+ size_t alcn, zlen, zeroes, zlcn, zlen2, ztrim, new_zlen;
|
|
Kmods SIG |
d83023 |
struct wnd_bitmap *wnd = &sbi->used.bitmap;
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
down_write_nested(&wnd->rw_lock, BITMAP_MUTEX_CLUSTERS);
|
|
Kmods SIG |
d83023 |
if (opt & ALLOCATE_MFT) {
|
|
Kmods SIG |
d83023 |
- CLST alen;
|
|
Kmods SIG |
d83023 |
-
|
|
Kmods SIG |
d83023 |
zlen = wnd_zone_len(wnd);
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
if (!zlen) {
|
|
Kmods SIG |
d83023 |
err = ntfs_refresh_zone(sbi);
|
|
Kmods SIG |
d83023 |
if (err)
|
|
Kmods SIG |
d83023 |
goto out;
|
|
Kmods SIG |
d83023 |
-
|
|
Kmods SIG |
d83023 |
zlen = wnd_zone_len(wnd);
|
|
Kmods SIG |
d83023 |
+ }
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
- if (!zlen) {
|
|
Kmods SIG |
d83023 |
- ntfs_err(sbi->sb,
|
|
Kmods SIG |
d83023 |
- "no free space to extend mft");
|
|
Kmods SIG |
d83023 |
- err = -ENOSPC;
|
|
Kmods SIG |
d83023 |
- goto out;
|
|
Kmods SIG |
d83023 |
- }
|
|
Kmods SIG |
d83023 |
+ if (!zlen) {
|
|
Kmods SIG |
d83023 |
+ ntfs_err(sbi->sb, "no free space to extend mft");
|
|
Kmods SIG |
d83023 |
+ goto out;
|
|
Kmods SIG |
d83023 |
}
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
lcn = wnd_zone_bit(wnd);
|
|
Kmods SIG |
d83023 |
@@ -389,14 +385,13 @@ int ntfs_look_for_free_space(struct ntfs_sb_info *sbi, CLST lcn, CLST len,
|
|
Kmods SIG |
d83023 |
wnd_zone_set(wnd, lcn + alen, zlen - alen);
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
err = wnd_set_used(wnd, lcn, alen);
|
|
Kmods SIG |
d83023 |
- if (err)
|
|
Kmods SIG |
d83023 |
- goto out;
|
|
Kmods SIG |
d83023 |
-
|
|
Kmods SIG |
d83023 |
- *new_lcn = lcn;
|
|
Kmods SIG |
d83023 |
- *new_len = alen;
|
|
Kmods SIG |
d83023 |
- goto ok;
|
|
Kmods SIG |
d83023 |
+ if (err) {
|
|
Kmods SIG |
d83023 |
+ up_write(&wnd->rw_lock);
|
|
Kmods SIG |
d83023 |
+ return err;
|
|
Kmods SIG |
d83023 |
+ }
|
|
Kmods SIG |
d83023 |
+ alcn = lcn;
|
|
Kmods SIG |
d83023 |
+ goto out;
|
|
Kmods SIG |
d83023 |
}
|
|
Kmods SIG |
d83023 |
-
|
|
Kmods SIG |
d83023 |
/*
|
|
Kmods SIG |
d83023 |
* 'Cause cluster 0 is always used this value means that we should use
|
|
Kmods SIG |
d83023 |
* cached value of 'next_free_lcn' to improve performance.
|
|
Kmods SIG |
d83023 |
@@ -407,22 +402,17 @@ int ntfs_look_for_free_space(struct ntfs_sb_info *sbi, CLST lcn, CLST len,
|
|
Kmods SIG |
d83023 |
if (lcn >= wnd->nbits)
|
|
Kmods SIG |
d83023 |
lcn = 0;
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
- *new_len = wnd_find(wnd, len, lcn, BITMAP_FIND_MARK_AS_USED, &a_lcn);
|
|
Kmods SIG |
d83023 |
- if (*new_len) {
|
|
Kmods SIG |
d83023 |
- *new_lcn = a_lcn;
|
|
Kmods SIG |
d83023 |
- goto ok;
|
|
Kmods SIG |
d83023 |
- }
|
|
Kmods SIG |
d83023 |
+ alen = wnd_find(wnd, len, lcn, BITMAP_FIND_MARK_AS_USED, &alcn);
|
|
Kmods SIG |
d83023 |
+ if (alen)
|
|
Kmods SIG |
d83023 |
+ goto out;
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
/* Try to use clusters from MftZone. */
|
|
Kmods SIG |
d83023 |
zlen = wnd_zone_len(wnd);
|
|
Kmods SIG |
d83023 |
zeroes = wnd_zeroes(wnd);
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
- /* Check too big request. */
|
|
Kmods SIG |
d83023 |
- if (len > zeroes + zlen)
|
|
Kmods SIG |
d83023 |
- goto no_space;
|
|
Kmods SIG |
d83023 |
-
|
|
Kmods SIG |
d83023 |
- if (zlen <= NTFS_MIN_MFT_ZONE)
|
|
Kmods SIG |
d83023 |
- goto no_space;
|
|
Kmods SIG |
d83023 |
+ /* Check too big request */
|
|
Kmods SIG |
d83023 |
+ if (len > zeroes + zlen || zlen <= NTFS_MIN_MFT_ZONE)
|
|
Kmods SIG |
d83023 |
+ goto out;
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
/* How many clusters to cat from zone. */
|
|
Kmods SIG |
d83023 |
zlcn = wnd_zone_bit(wnd);
|
|
Kmods SIG |
d83023 |
@@ -439,31 +429,24 @@ int ntfs_look_for_free_space(struct ntfs_sb_info *sbi, CLST lcn, CLST len,
|
|
Kmods SIG |
d83023 |
wnd_zone_set(wnd, zlcn, new_zlen);
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
/* Allocate continues clusters. */
|
|
Kmods SIG |
d83023 |
- *new_len =
|
|
Kmods SIG |
d83023 |
- wnd_find(wnd, len, 0,
|
|
Kmods SIG |
d83023 |
- BITMAP_FIND_MARK_AS_USED | BITMAP_FIND_FULL, &a_lcn);
|
|
Kmods SIG |
d83023 |
- if (*new_len) {
|
|
Kmods SIG |
d83023 |
- *new_lcn = a_lcn;
|
|
Kmods SIG |
d83023 |
- goto ok;
|
|
Kmods SIG |
d83023 |
- }
|
|
Kmods SIG |
d83023 |
-
|
|
Kmods SIG |
d83023 |
-no_space:
|
|
Kmods SIG |
d83023 |
- up_write(&wnd->rw_lock);
|
|
Kmods SIG |
d83023 |
-
|
|
Kmods SIG |
d83023 |
- return -ENOSPC;
|
|
Kmods SIG |
d83023 |
-
|
|
Kmods SIG |
d83023 |
-ok:
|
|
Kmods SIG |
d83023 |
- err = 0;
|
|
Kmods SIG |
d83023 |
+ alen = wnd_find(wnd, len, 0,
|
|
Kmods SIG |
d83023 |
+ BITMAP_FIND_MARK_AS_USED | BITMAP_FIND_FULL, &alcn);
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
- ntfs_unmap_meta(sb, *new_lcn, *new_len);
|
|
Kmods SIG |
d83023 |
+out:
|
|
Kmods SIG |
d83023 |
+ if (alen) {
|
|
Kmods SIG |
d83023 |
+ err = 0;
|
|
Kmods SIG |
d83023 |
+ *new_len = alen;
|
|
Kmods SIG |
d83023 |
+ *new_lcn = alcn;
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
- if (opt & ALLOCATE_MFT)
|
|
Kmods SIG |
d83023 |
- goto out;
|
|
Kmods SIG |
d83023 |
+ ntfs_unmap_meta(sb, alcn, alen);
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
- /* Set hint for next requests. */
|
|
Kmods SIG |
d83023 |
- sbi->used.next_free_lcn = *new_lcn + *new_len;
|
|
Kmods SIG |
d83023 |
+ /* Set hint for next requests. */
|
|
Kmods SIG |
d83023 |
+ if (!(opt & ALLOCATE_MFT))
|
|
Kmods SIG |
d83023 |
+ sbi->used.next_free_lcn = alcn + alen;
|
|
Kmods SIG |
d83023 |
+ } else {
|
|
Kmods SIG |
d83023 |
+ err = -ENOSPC;
|
|
Kmods SIG |
d83023 |
+ }
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
-out:
|
|
Kmods SIG |
d83023 |
up_write(&wnd->rw_lock);
|
|
Kmods SIG |
d83023 |
return err;
|
|
Kmods SIG |
d83023 |
}
|
|
Kmods SIG |
d83023 |
@@ -2226,7 +2209,7 @@ int ntfs_insert_security(struct ntfs_sb_info *sbi,
|
|
Kmods SIG |
d83023 |
sii_e.sec_id = d_security->key.sec_id;
|
|
Kmods SIG |
d83023 |
memcpy(&sii_e.sec_hdr, d_security, SIZEOF_SECURITY_HDR);
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
- err = indx_insert_entry(indx_sii, ni, &sii_e.de, NULL, NULL);
|
|
Kmods SIG |
d83023 |
+ err = indx_insert_entry(indx_sii, ni, &sii_e.de, NULL, NULL, 0);
|
|
Kmods SIG |
d83023 |
if (err)
|
|
Kmods SIG |
d83023 |
goto out;
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
@@ -2247,7 +2230,7 @@ int ntfs_insert_security(struct ntfs_sb_info *sbi,
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
fnd_clear(fnd_sdh);
|
|
Kmods SIG |
d83023 |
err = indx_insert_entry(indx_sdh, ni, &sdh_e.de, (void *)(size_t)1,
|
|
Kmods SIG |
d83023 |
- fnd_sdh);
|
|
Kmods SIG |
d83023 |
+ fnd_sdh, 0);
|
|
Kmods SIG |
d83023 |
if (err)
|
|
Kmods SIG |
d83023 |
goto out;
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
@@ -2385,7 +2368,7 @@ int ntfs_insert_reparse(struct ntfs_sb_info *sbi, __le32 rtag,
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
mutex_lock_nested(&ni->ni_lock, NTFS_INODE_MUTEX_REPARSE);
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
- err = indx_insert_entry(indx, ni, &re.de, NULL, NULL);
|
|
Kmods SIG |
d83023 |
+ err = indx_insert_entry(indx, ni, &re.de, NULL, NULL, 0);
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
mark_inode_dirty(&ni->vfs_inode);
|
|
Kmods SIG |
d83023 |
ni_unlock(ni);
|
|
Kmods SIG |
d83023 |
diff --git a/src/index.c b/src/index.c
|
|
Kmods SIG |
d83023 |
index 70ef59455b72c927b40bbb76c5420b8dfc72e24a..1224b8e42b3e3d07938310739843f0ab7195f326 100644
|
|
Kmods SIG |
d83023 |
--- a/src/index.c
|
|
Kmods SIG |
d83023 |
+++ b/src/index.c
|
|
Kmods SIG |
d83023 |
@@ -1427,7 +1427,7 @@ static int indx_create_allocate(struct ntfs_index *indx, struct ntfs_inode *ni,
|
|
Kmods SIG |
d83023 |
alloc->nres.valid_size = alloc->nres.data_size = cpu_to_le64(data_size);
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
err = ni_insert_resident(ni, bitmap_size(1), ATTR_BITMAP, in->name,
|
|
Kmods SIG |
d83023 |
- in->name_len, &bitmap, NULL);
|
|
Kmods SIG |
d83023 |
+ in->name_len, &bitmap, NULL, NULL);
|
|
Kmods SIG |
d83023 |
if (err)
|
|
Kmods SIG |
d83023 |
goto out2;
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
@@ -1443,7 +1443,7 @@ static int indx_create_allocate(struct ntfs_index *indx, struct ntfs_inode *ni,
|
|
Kmods SIG |
d83023 |
return 0;
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
out2:
|
|
Kmods SIG |
d83023 |
- mi_remove_attr(&ni->mi, alloc);
|
|
Kmods SIG |
d83023 |
+ mi_remove_attr(NULL, &ni->mi, alloc);
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
out1:
|
|
Kmods SIG |
d83023 |
run_deallocate(sbi, &run, false);
|
|
Kmods SIG |
d83023 |
@@ -1529,24 +1529,24 @@ static int indx_add_allocate(struct ntfs_index *indx, struct ntfs_inode *ni,
|
|
Kmods SIG |
d83023 |
/*
|
|
Kmods SIG |
d83023 |
* indx_insert_into_root - Attempt to insert an entry into the index root.
|
|
Kmods SIG |
d83023 |
*
|
|
Kmods SIG |
d83023 |
+ * @undo - True if we undoing previous remove.
|
|
Kmods SIG |
d83023 |
* If necessary, it will twiddle the index b-tree.
|
|
Kmods SIG |
d83023 |
*/
|
|
Kmods SIG |
d83023 |
static int indx_insert_into_root(struct ntfs_index *indx, struct ntfs_inode *ni,
|
|
Kmods SIG |
d83023 |
const struct NTFS_DE *new_de,
|
|
Kmods SIG |
d83023 |
struct NTFS_DE *root_de, const void *ctx,
|
|
Kmods SIG |
d83023 |
- struct ntfs_fnd *fnd)
|
|
Kmods SIG |
d83023 |
+ struct ntfs_fnd *fnd, bool undo)
|
|
Kmods SIG |
d83023 |
{
|
|
Kmods SIG |
d83023 |
int err = 0;
|
|
Kmods SIG |
d83023 |
struct NTFS_DE *e, *e0, *re;
|
|
Kmods SIG |
d83023 |
struct mft_inode *mi;
|
|
Kmods SIG |
d83023 |
struct ATTRIB *attr;
|
|
Kmods SIG |
d83023 |
- struct MFT_REC *rec;
|
|
Kmods SIG |
d83023 |
struct INDEX_HDR *hdr;
|
|
Kmods SIG |
d83023 |
struct indx_node *n;
|
|
Kmods SIG |
d83023 |
CLST new_vbn;
|
|
Kmods SIG |
d83023 |
__le64 *sub_vbn, t_vbn;
|
|
Kmods SIG |
d83023 |
u16 new_de_size;
|
|
Kmods SIG |
d83023 |
- u32 hdr_used, hdr_total, asize, used, to_move;
|
|
Kmods SIG |
d83023 |
+ u32 hdr_used, hdr_total, asize, to_move;
|
|
Kmods SIG |
d83023 |
u32 root_size, new_root_size;
|
|
Kmods SIG |
d83023 |
struct ntfs_sb_info *sbi;
|
|
Kmods SIG |
d83023 |
int ds_root;
|
|
Kmods SIG |
d83023 |
@@ -1559,12 +1559,11 @@ static int indx_insert_into_root(struct ntfs_index *indx, struct ntfs_inode *ni,
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
/*
|
|
Kmods SIG |
d83023 |
* Try easy case:
|
|
Kmods SIG |
d83023 |
- * hdr_insert_de will succeed if there's room the root for the new entry.
|
|
Kmods SIG |
d83023 |
+ * hdr_insert_de will succeed if there's
|
|
Kmods SIG |
d83023 |
+ * room the root for the new entry.
|
|
Kmods SIG |
d83023 |
*/
|
|
Kmods SIG |
d83023 |
hdr = &root->ihdr;
|
|
Kmods SIG |
d83023 |
sbi = ni->mi.sbi;
|
|
Kmods SIG |
d83023 |
- rec = mi->mrec;
|
|
Kmods SIG |
d83023 |
- used = le32_to_cpu(rec->used);
|
|
Kmods SIG |
d83023 |
new_de_size = le16_to_cpu(new_de->size);
|
|
Kmods SIG |
d83023 |
hdr_used = le32_to_cpu(hdr->used);
|
|
Kmods SIG |
d83023 |
hdr_total = le32_to_cpu(hdr->total);
|
|
Kmods SIG |
d83023 |
@@ -1573,9 +1572,9 @@ static int indx_insert_into_root(struct ntfs_index *indx, struct ntfs_inode *ni,
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
ds_root = new_de_size + hdr_used - hdr_total;
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
- if (used + ds_root < sbi->max_bytes_per_attr) {
|
|
Kmods SIG |
d83023 |
- /* Make a room for new elements. */
|
|
Kmods SIG |
d83023 |
- mi_resize_attr(mi, attr, ds_root);
|
|
Kmods SIG |
d83023 |
+ /* If 'undo' is set then reduce requirements. */
|
|
Kmods SIG |
d83023 |
+ if ((undo || asize + ds_root < sbi->max_bytes_per_attr) &&
|
|
Kmods SIG |
d83023 |
+ mi_resize_attr(mi, attr, ds_root)) {
|
|
Kmods SIG |
d83023 |
hdr->total = cpu_to_le32(hdr_total + ds_root);
|
|
Kmods SIG |
d83023 |
e = hdr_insert_de(indx, hdr, new_de, root_de, ctx);
|
|
Kmods SIG |
d83023 |
WARN_ON(!e);
|
|
Kmods SIG |
d83023 |
@@ -1629,7 +1628,7 @@ static int indx_insert_into_root(struct ntfs_index *indx, struct ntfs_inode *ni,
|
|
Kmods SIG |
d83023 |
sizeof(u64);
|
|
Kmods SIG |
d83023 |
ds_root = new_root_size - root_size;
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
- if (ds_root > 0 && used + ds_root > sbi->max_bytes_per_attr) {
|
|
Kmods SIG |
d83023 |
+ if (ds_root > 0 && asize + ds_root > sbi->max_bytes_per_attr) {
|
|
Kmods SIG |
d83023 |
/* Make root external. */
|
|
Kmods SIG |
d83023 |
err = -EOPNOTSUPP;
|
|
Kmods SIG |
d83023 |
goto out_free_re;
|
|
Kmods SIG |
d83023 |
@@ -1710,7 +1709,7 @@ static int indx_insert_into_root(struct ntfs_index *indx, struct ntfs_inode *ni,
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
put_indx_node(n);
|
|
Kmods SIG |
d83023 |
fnd_clear(fnd);
|
|
Kmods SIG |
d83023 |
- err = indx_insert_entry(indx, ni, new_de, ctx, fnd);
|
|
Kmods SIG |
d83023 |
+ err = indx_insert_entry(indx, ni, new_de, ctx, fnd, undo);
|
|
Kmods SIG |
d83023 |
goto out_free_root;
|
|
Kmods SIG |
d83023 |
}
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
@@ -1854,7 +1853,7 @@ indx_insert_into_buffer(struct ntfs_index *indx, struct ntfs_inode *ni,
|
|
Kmods SIG |
d83023 |
*/
|
|
Kmods SIG |
d83023 |
if (!level) {
|
|
Kmods SIG |
d83023 |
/* Insert in root. */
|
|
Kmods SIG |
d83023 |
- err = indx_insert_into_root(indx, ni, up_e, NULL, ctx, fnd);
|
|
Kmods SIG |
d83023 |
+ err = indx_insert_into_root(indx, ni, up_e, NULL, ctx, fnd, 0);
|
|
Kmods SIG |
d83023 |
if (err)
|
|
Kmods SIG |
d83023 |
goto out;
|
|
Kmods SIG |
d83023 |
} else {
|
|
Kmods SIG |
d83023 |
@@ -1876,10 +1875,12 @@ indx_insert_into_buffer(struct ntfs_index *indx, struct ntfs_inode *ni,
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
/*
|
|
Kmods SIG |
d83023 |
* indx_insert_entry - Insert new entry into index.
|
|
Kmods SIG |
d83023 |
+ *
|
|
Kmods SIG |
d83023 |
+ * @undo - True if we undoing previous remove.
|
|
Kmods SIG |
d83023 |
*/
|
|
Kmods SIG |
d83023 |
int indx_insert_entry(struct ntfs_index *indx, struct ntfs_inode *ni,
|
|
Kmods SIG |
d83023 |
const struct NTFS_DE *new_de, const void *ctx,
|
|
Kmods SIG |
d83023 |
- struct ntfs_fnd *fnd)
|
|
Kmods SIG |
d83023 |
+ struct ntfs_fnd *fnd, bool undo)
|
|
Kmods SIG |
d83023 |
{
|
|
Kmods SIG |
d83023 |
int err;
|
|
Kmods SIG |
d83023 |
int diff;
|
|
Kmods SIG |
d83023 |
@@ -1925,7 +1926,7 @@ int indx_insert_entry(struct ntfs_index *indx, struct ntfs_inode *ni,
|
|
Kmods SIG |
d83023 |
* new entry into it.
|
|
Kmods SIG |
d83023 |
*/
|
|
Kmods SIG |
d83023 |
err = indx_insert_into_root(indx, ni, new_de, fnd->root_de, ctx,
|
|
Kmods SIG |
d83023 |
- fnd);
|
|
Kmods SIG |
d83023 |
+ fnd, undo);
|
|
Kmods SIG |
d83023 |
if (err)
|
|
Kmods SIG |
d83023 |
goto out;
|
|
Kmods SIG |
d83023 |
} else {
|
|
Kmods SIG |
d83023 |
@@ -2302,7 +2303,7 @@ int indx_delete_entry(struct ntfs_index *indx, struct ntfs_inode *ni,
|
|
Kmods SIG |
d83023 |
fnd->level - 1,
|
|
Kmods SIG |
d83023 |
fnd)
|
|
Kmods SIG |
d83023 |
: indx_insert_into_root(indx, ni, re, e,
|
|
Kmods SIG |
d83023 |
- ctx, fnd);
|
|
Kmods SIG |
d83023 |
+ ctx, fnd, 0);
|
|
Kmods SIG |
d83023 |
kfree(re);
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
if (err)
|
|
Kmods SIG |
d83023 |
@@ -2507,7 +2508,7 @@ int indx_delete_entry(struct ntfs_index *indx, struct ntfs_inode *ni,
|
|
Kmods SIG |
d83023 |
* Re-insert the entry into the tree.
|
|
Kmods SIG |
d83023 |
* Find the spot the tree where we want to insert the new entry.
|
|
Kmods SIG |
d83023 |
*/
|
|
Kmods SIG |
d83023 |
- err = indx_insert_entry(indx, ni, me, ctx, fnd);
|
|
Kmods SIG |
d83023 |
+ err = indx_insert_entry(indx, ni, me, ctx, fnd, 0);
|
|
Kmods SIG |
d83023 |
kfree(me);
|
|
Kmods SIG |
d83023 |
if (err)
|
|
Kmods SIG |
d83023 |
goto out;
|
|
Kmods SIG |
d83023 |
@@ -2595,10 +2596,8 @@ int indx_update_dup(struct ntfs_inode *ni, struct ntfs_sb_info *sbi,
|
|
Kmods SIG |
d83023 |
struct ntfs_index *indx = &ni->dir;
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
fnd = fnd_get();
|
|
Kmods SIG |
d83023 |
- if (!fnd) {
|
|
Kmods SIG |
d83023 |
- err = -ENOMEM;
|
|
Kmods SIG |
d83023 |
- goto out1;
|
|
Kmods SIG |
d83023 |
- }
|
|
Kmods SIG |
d83023 |
+ if (!fnd)
|
|
Kmods SIG |
d83023 |
+ return -ENOMEM;
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
root = indx_get_root(indx, ni, NULL, &mi);
|
|
Kmods SIG |
d83023 |
if (!root) {
|
|
Kmods SIG |
d83023 |
@@ -2645,7 +2644,5 @@ int indx_update_dup(struct ntfs_inode *ni, struct ntfs_sb_info *sbi,
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
out:
|
|
Kmods SIG |
d83023 |
fnd_put(fnd);
|
|
Kmods SIG |
d83023 |
-
|
|
Kmods SIG |
d83023 |
-out1:
|
|
Kmods SIG |
d83023 |
return err;
|
|
Kmods SIG |
d83023 |
}
|
|
Kmods SIG |
d83023 |
diff --git a/src/inode.c b/src/inode.c
|
|
Kmods SIG |
d83023 |
index b86ec7dd731cea9fd0b41abb40fe4d81ca965c13..8f72066b3229a3f87b7b0b0e770bce20a4b06edd 100644
|
|
Kmods SIG |
d83023 |
--- a/src/inode.c
|
|
Kmods SIG |
d83023 |
+++ b/src/inode.c
|
|
Kmods SIG |
d83023 |
@@ -399,6 +399,12 @@ static struct inode *ntfs_read_mft(struct inode *inode,
|
|
Kmods SIG |
d83023 |
goto out;
|
|
Kmods SIG |
d83023 |
}
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
+ if (names != le16_to_cpu(rec->hard_links)) {
|
|
Kmods SIG |
d83023 |
+ /* Correct minor error on the fly. Do not mark inode as dirty. */
|
|
Kmods SIG |
d83023 |
+ rec->hard_links = cpu_to_le16(names);
|
|
Kmods SIG |
d83023 |
+ ni->mi.dirty = true;
|
|
Kmods SIG |
d83023 |
+ }
|
|
Kmods SIG |
d83023 |
+
|
|
Kmods SIG |
d83023 |
set_nlink(inode, names);
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
if (S_ISDIR(mode)) {
|
|
Kmods SIG |
d83023 |
@@ -1279,6 +1285,7 @@ struct inode *ntfs_create_inode(struct user_namespace *mnt_userns,
|
|
Kmods SIG |
d83023 |
}
|
|
Kmods SIG |
d83023 |
inode = &ni->vfs_inode;
|
|
Kmods SIG |
d83023 |
inode_init_owner(mnt_userns, inode, dir, mode);
|
|
Kmods SIG |
d83023 |
+ mode = inode->i_mode;
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
inode->i_atime = inode->i_mtime = inode->i_ctime = ni->i_crtime =
|
|
Kmods SIG |
d83023 |
current_time(inode);
|
|
Kmods SIG |
d83023 |
@@ -1371,6 +1378,7 @@ struct inode *ntfs_create_inode(struct user_namespace *mnt_userns,
|
|
Kmods SIG |
d83023 |
attr = Add2Ptr(attr, asize);
|
|
Kmods SIG |
d83023 |
}
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
+ attr->id = cpu_to_le16(aid++);
|
|
Kmods SIG |
d83023 |
if (fa & FILE_ATTRIBUTE_DIRECTORY) {
|
|
Kmods SIG |
d83023 |
/*
|
|
Kmods SIG |
d83023 |
* Regular directory or symlink to directory.
|
|
Kmods SIG |
d83023 |
@@ -1381,7 +1389,6 @@ struct inode *ntfs_create_inode(struct user_namespace *mnt_userns,
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
attr->type = ATTR_ROOT;
|
|
Kmods SIG |
d83023 |
attr->size = cpu_to_le32(asize);
|
|
Kmods SIG |
d83023 |
- attr->id = cpu_to_le16(aid++);
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
attr->name_len = ARRAY_SIZE(I30_NAME);
|
|
Kmods SIG |
d83023 |
attr->name_off = SIZEOF_RESIDENT_LE;
|
|
Kmods SIG |
d83023 |
@@ -1412,52 +1419,46 @@ struct inode *ntfs_create_inode(struct user_namespace *mnt_userns,
|
|
Kmods SIG |
d83023 |
/* Insert empty ATTR_DATA */
|
|
Kmods SIG |
d83023 |
attr->type = ATTR_DATA;
|
|
Kmods SIG |
d83023 |
attr->size = cpu_to_le32(SIZEOF_RESIDENT);
|
|
Kmods SIG |
d83023 |
- attr->id = cpu_to_le16(aid++);
|
|
Kmods SIG |
d83023 |
attr->name_off = SIZEOF_RESIDENT_LE;
|
|
Kmods SIG |
d83023 |
attr->res.data_off = SIZEOF_RESIDENT_LE;
|
|
Kmods SIG |
d83023 |
- } else {
|
|
Kmods SIG |
d83023 |
+ } else if (S_ISREG(mode)) {
|
|
Kmods SIG |
d83023 |
/*
|
|
Kmods SIG |
d83023 |
- * Regular file or node.
|
|
Kmods SIG |
d83023 |
+ * Regular file. Create empty non resident data attribute.
|
|
Kmods SIG |
d83023 |
*/
|
|
Kmods SIG |
d83023 |
attr->type = ATTR_DATA;
|
|
Kmods SIG |
d83023 |
- attr->id = cpu_to_le16(aid++);
|
|
Kmods SIG |
d83023 |
-
|
|
Kmods SIG |
d83023 |
- if (S_ISREG(mode)) {
|
|
Kmods SIG |
d83023 |
- /* Create empty non resident data attribute. */
|
|
Kmods SIG |
d83023 |
- attr->non_res = 1;
|
|
Kmods SIG |
d83023 |
- attr->nres.evcn = cpu_to_le64(-1ll);
|
|
Kmods SIG |
d83023 |
- if (fa & FILE_ATTRIBUTE_SPARSE_FILE) {
|
|
Kmods SIG |
d83023 |
- attr->size =
|
|
Kmods SIG |
d83023 |
- cpu_to_le32(SIZEOF_NONRESIDENT_EX + 8);
|
|
Kmods SIG |
d83023 |
- attr->name_off = SIZEOF_NONRESIDENT_EX_LE;
|
|
Kmods SIG |
d83023 |
- attr->flags = ATTR_FLAG_SPARSED;
|
|
Kmods SIG |
d83023 |
- asize = SIZEOF_NONRESIDENT_EX + 8;
|
|
Kmods SIG |
d83023 |
- } else if (fa & FILE_ATTRIBUTE_COMPRESSED) {
|
|
Kmods SIG |
d83023 |
- attr->size =
|
|
Kmods SIG |
d83023 |
- cpu_to_le32(SIZEOF_NONRESIDENT_EX + 8);
|
|
Kmods SIG |
d83023 |
- attr->name_off = SIZEOF_NONRESIDENT_EX_LE;
|
|
Kmods SIG |
d83023 |
- attr->flags = ATTR_FLAG_COMPRESSED;
|
|
Kmods SIG |
d83023 |
- attr->nres.c_unit = COMPRESSION_UNIT;
|
|
Kmods SIG |
d83023 |
- asize = SIZEOF_NONRESIDENT_EX + 8;
|
|
Kmods SIG |
d83023 |
- } else {
|
|
Kmods SIG |
d83023 |
- attr->size =
|
|
Kmods SIG |
d83023 |
- cpu_to_le32(SIZEOF_NONRESIDENT + 8);
|
|
Kmods SIG |
d83023 |
- attr->name_off = SIZEOF_NONRESIDENT_LE;
|
|
Kmods SIG |
d83023 |
- asize = SIZEOF_NONRESIDENT + 8;
|
|
Kmods SIG |
d83023 |
- }
|
|
Kmods SIG |
d83023 |
- attr->nres.run_off = attr->name_off;
|
|
Kmods SIG |
d83023 |
+ attr->non_res = 1;
|
|
Kmods SIG |
d83023 |
+ attr->nres.evcn = cpu_to_le64(-1ll);
|
|
Kmods SIG |
d83023 |
+ if (fa & FILE_ATTRIBUTE_SPARSE_FILE) {
|
|
Kmods SIG |
d83023 |
+ attr->size = cpu_to_le32(SIZEOF_NONRESIDENT_EX + 8);
|
|
Kmods SIG |
d83023 |
+ attr->name_off = SIZEOF_NONRESIDENT_EX_LE;
|
|
Kmods SIG |
d83023 |
+ attr->flags = ATTR_FLAG_SPARSED;
|
|
Kmods SIG |
d83023 |
+ asize = SIZEOF_NONRESIDENT_EX + 8;
|
|
Kmods SIG |
d83023 |
+ } else if (fa & FILE_ATTRIBUTE_COMPRESSED) {
|
|
Kmods SIG |
d83023 |
+ attr->size = cpu_to_le32(SIZEOF_NONRESIDENT_EX + 8);
|
|
Kmods SIG |
d83023 |
+ attr->name_off = SIZEOF_NONRESIDENT_EX_LE;
|
|
Kmods SIG |
d83023 |
+ attr->flags = ATTR_FLAG_COMPRESSED;
|
|
Kmods SIG |
d83023 |
+ attr->nres.c_unit = COMPRESSION_UNIT;
|
|
Kmods SIG |
d83023 |
+ asize = SIZEOF_NONRESIDENT_EX + 8;
|
|
Kmods SIG |
d83023 |
} else {
|
|
Kmods SIG |
d83023 |
- /* Create empty resident data attribute. */
|
|
Kmods SIG |
d83023 |
- attr->size = cpu_to_le32(SIZEOF_RESIDENT);
|
|
Kmods SIG |
d83023 |
- attr->name_off = SIZEOF_RESIDENT_LE;
|
|
Kmods SIG |
d83023 |
- if (fa & FILE_ATTRIBUTE_SPARSE_FILE)
|
|
Kmods SIG |
d83023 |
- attr->flags = ATTR_FLAG_SPARSED;
|
|
Kmods SIG |
d83023 |
- else if (fa & FILE_ATTRIBUTE_COMPRESSED)
|
|
Kmods SIG |
d83023 |
- attr->flags = ATTR_FLAG_COMPRESSED;
|
|
Kmods SIG |
d83023 |
- attr->res.data_off = SIZEOF_RESIDENT_LE;
|
|
Kmods SIG |
d83023 |
- asize = SIZEOF_RESIDENT;
|
|
Kmods SIG |
d83023 |
- ni->ni_flags |= NI_FLAG_RESIDENT;
|
|
Kmods SIG |
d83023 |
+ attr->size = cpu_to_le32(SIZEOF_NONRESIDENT + 8);
|
|
Kmods SIG |
d83023 |
+ attr->name_off = SIZEOF_NONRESIDENT_LE;
|
|
Kmods SIG |
d83023 |
+ asize = SIZEOF_NONRESIDENT + 8;
|
|
Kmods SIG |
d83023 |
}
|
|
Kmods SIG |
d83023 |
+ attr->nres.run_off = attr->name_off;
|
|
Kmods SIG |
d83023 |
+ } else {
|
|
Kmods SIG |
d83023 |
+ /*
|
|
Kmods SIG |
d83023 |
+ * Node. Create empty resident data attribute.
|
|
Kmods SIG |
d83023 |
+ */
|
|
Kmods SIG |
d83023 |
+ attr->type = ATTR_DATA;
|
|
Kmods SIG |
d83023 |
+ attr->size = cpu_to_le32(SIZEOF_RESIDENT);
|
|
Kmods SIG |
d83023 |
+ attr->name_off = SIZEOF_RESIDENT_LE;
|
|
Kmods SIG |
d83023 |
+ if (fa & FILE_ATTRIBUTE_SPARSE_FILE)
|
|
Kmods SIG |
d83023 |
+ attr->flags = ATTR_FLAG_SPARSED;
|
|
Kmods SIG |
d83023 |
+ else if (fa & FILE_ATTRIBUTE_COMPRESSED)
|
|
Kmods SIG |
d83023 |
+ attr->flags = ATTR_FLAG_COMPRESSED;
|
|
Kmods SIG |
d83023 |
+ attr->res.data_off = SIZEOF_RESIDENT_LE;
|
|
Kmods SIG |
d83023 |
+ asize = SIZEOF_RESIDENT;
|
|
Kmods SIG |
d83023 |
+ ni->ni_flags |= NI_FLAG_RESIDENT;
|
|
Kmods SIG |
d83023 |
}
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
if (S_ISDIR(mode)) {
|
|
Kmods SIG |
d83023 |
@@ -1485,7 +1486,8 @@ struct inode *ntfs_create_inode(struct user_namespace *mnt_userns,
|
|
Kmods SIG |
d83023 |
asize = ALIGN(SIZEOF_RESIDENT + nsize, 8);
|
|
Kmods SIG |
d83023 |
t16 = PtrOffset(rec, attr);
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
- if (asize + t16 + 8 > sbi->record_size) {
|
|
Kmods SIG |
d83023 |
+ /* 0x78 - the size of EA + EAINFO to store WSL */
|
|
Kmods SIG |
d83023 |
+ if (asize + t16 + 0x78 + 8 > sbi->record_size) {
|
|
Kmods SIG |
d83023 |
CLST alen;
|
|
Kmods SIG |
d83023 |
CLST clst = bytes_to_cluster(sbi, nsize);
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
@@ -1545,20 +1547,15 @@ struct inode *ntfs_create_inode(struct user_namespace *mnt_userns,
|
|
Kmods SIG |
d83023 |
rec->next_attr_id = cpu_to_le16(aid);
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
/* Step 2: Add new name in index. */
|
|
Kmods SIG |
d83023 |
- err = indx_insert_entry(&dir_ni->dir, dir_ni, new_de, sbi, fnd);
|
|
Kmods SIG |
d83023 |
+ err = indx_insert_entry(&dir_ni->dir, dir_ni, new_de, sbi, fnd, 0);
|
|
Kmods SIG |
d83023 |
if (err)
|
|
Kmods SIG |
d83023 |
goto out6;
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
- /* Update current directory record. */
|
|
Kmods SIG |
d83023 |
- mark_inode_dirty(dir);
|
|
Kmods SIG |
d83023 |
-
|
|
Kmods SIG |
d83023 |
inode->i_generation = le16_to_cpu(rec->seq);
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
dir->i_mtime = dir->i_ctime = inode->i_atime;
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
if (S_ISDIR(mode)) {
|
|
Kmods SIG |
d83023 |
- if (dir->i_mode & S_ISGID)
|
|
Kmods SIG |
d83023 |
- mode |= S_ISGID;
|
|
Kmods SIG |
d83023 |
inode->i_op = &ntfs_dir_inode_operations;
|
|
Kmods SIG |
d83023 |
inode->i_fop = &ntfs_dir_operations;
|
|
Kmods SIG |
d83023 |
} else if (S_ISLNK(mode)) {
|
|
Kmods SIG |
d83023 |
@@ -1601,8 +1598,8 @@ struct inode *ntfs_create_inode(struct user_namespace *mnt_userns,
|
|
Kmods SIG |
d83023 |
d_instantiate(dentry, inode);
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
ntfs_save_wsl_perm(inode);
|
|
Kmods SIG |
d83023 |
- mark_inode_dirty(inode);
|
|
Kmods SIG |
d83023 |
mark_inode_dirty(dir);
|
|
Kmods SIG |
d83023 |
+ mark_inode_dirty(inode);
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
/* Normal exit. */
|
|
Kmods SIG |
d83023 |
goto out2;
|
|
Kmods SIG |
d83023 |
@@ -1646,61 +1643,36 @@ struct inode *ntfs_create_inode(struct user_namespace *mnt_userns,
|
|
Kmods SIG |
d83023 |
int ntfs_link_inode(struct inode *inode, struct dentry *dentry)
|
|
Kmods SIG |
d83023 |
{
|
|
Kmods SIG |
d83023 |
int err;
|
|
Kmods SIG |
d83023 |
- struct inode *dir = d_inode(dentry->d_parent);
|
|
Kmods SIG |
d83023 |
- struct ntfs_inode *dir_ni = ntfs_i(dir);
|
|
Kmods SIG |
d83023 |
struct ntfs_inode *ni = ntfs_i(inode);
|
|
Kmods SIG |
d83023 |
- struct super_block *sb = inode->i_sb;
|
|
Kmods SIG |
d83023 |
- struct ntfs_sb_info *sbi = sb->s_fs_info;
|
|
Kmods SIG |
d83023 |
- const struct qstr *name = &dentry->d_name;
|
|
Kmods SIG |
d83023 |
- struct NTFS_DE *new_de = NULL;
|
|
Kmods SIG |
d83023 |
- struct ATTR_FILE_NAME *fname;
|
|
Kmods SIG |
d83023 |
- struct ATTRIB *attr;
|
|
Kmods SIG |
d83023 |
- u16 key_size;
|
|
Kmods SIG |
d83023 |
- struct INDEX_ROOT *dir_root;
|
|
Kmods SIG |
d83023 |
-
|
|
Kmods SIG |
d83023 |
- dir_root = indx_get_root(&dir_ni->dir, dir_ni, NULL, NULL);
|
|
Kmods SIG |
d83023 |
- if (!dir_root)
|
|
Kmods SIG |
d83023 |
- return -EINVAL;
|
|
Kmods SIG |
d83023 |
+ struct ntfs_sb_info *sbi = inode->i_sb->s_fs_info;
|
|
Kmods SIG |
d83023 |
+ struct NTFS_DE *de;
|
|
Kmods SIG |
d83023 |
+ struct ATTR_FILE_NAME *de_name;
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
/* Allocate PATH_MAX bytes. */
|
|
Kmods SIG |
d83023 |
- new_de = __getname();
|
|
Kmods SIG |
d83023 |
- if (!new_de)
|
|
Kmods SIG |
d83023 |
+ de = __getname();
|
|
Kmods SIG |
d83023 |
+ if (!de)
|
|
Kmods SIG |
d83023 |
return -ENOMEM;
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
- /* Mark rw ntfs as dirty. It will be cleared at umount. */
|
|
Kmods SIG |
d83023 |
- ntfs_set_state(ni->mi.sbi, NTFS_DIRTY_DIRTY);
|
|
Kmods SIG |
d83023 |
-
|
|
Kmods SIG |
d83023 |
- /* Insert file name. */
|
|
Kmods SIG |
d83023 |
- err = fill_name_de(sbi, new_de, name, NULL);
|
|
Kmods SIG |
d83023 |
- if (err)
|
|
Kmods SIG |
d83023 |
- goto out;
|
|
Kmods SIG |
d83023 |
-
|
|
Kmods SIG |
d83023 |
- key_size = le16_to_cpu(new_de->key_size);
|
|
Kmods SIG |
d83023 |
- err = ni_insert_resident(ni, key_size, ATTR_NAME, NULL, 0, &attr, NULL);
|
|
Kmods SIG |
d83023 |
- if (err)
|
|
Kmods SIG |
d83023 |
- goto out;
|
|
Kmods SIG |
d83023 |
-
|
|
Kmods SIG |
d83023 |
- mi_get_ref(&ni->mi, &new_de->ref);
|
|
Kmods SIG |
d83023 |
-
|
|
Kmods SIG |
d83023 |
- fname = (struct ATTR_FILE_NAME *)(new_de + 1);
|
|
Kmods SIG |
d83023 |
- mi_get_ref(&dir_ni->mi, &fname->home);
|
|
Kmods SIG |
d83023 |
- fname->dup.cr_time = fname->dup.m_time = fname->dup.c_time =
|
|
Kmods SIG |
d83023 |
- fname->dup.a_time = kernel2nt(&inode->i_ctime);
|
|
Kmods SIG |
d83023 |
- fname->dup.alloc_size = fname->dup.data_size = 0;
|
|
Kmods SIG |
d83023 |
- fname->dup.fa = ni->std_fa;
|
|
Kmods SIG |
d83023 |
- fname->dup.ea_size = fname->dup.reparse = 0;
|
|
Kmods SIG |
d83023 |
-
|
|
Kmods SIG |
d83023 |
- memcpy(Add2Ptr(attr, SIZEOF_RESIDENT), fname, key_size);
|
|
Kmods SIG |
d83023 |
+ /* Mark rw ntfs as dirty. It will be cleared at umount. */
|
|
Kmods SIG |
d83023 |
+ ntfs_set_state(sbi, NTFS_DIRTY_DIRTY);
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
- err = indx_insert_entry(&dir_ni->dir, dir_ni, new_de, sbi, NULL);
|
|
Kmods SIG |
d83023 |
+ /* Construct 'de'. */
|
|
Kmods SIG |
d83023 |
+ err = fill_name_de(sbi, de, &dentry->d_name, NULL);
|
|
Kmods SIG |
d83023 |
if (err)
|
|
Kmods SIG |
d83023 |
goto out;
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
- le16_add_cpu(&ni->mi.mrec->hard_links, 1);
|
|
Kmods SIG |
d83023 |
- ni->mi.dirty = true;
|
|
Kmods SIG |
d83023 |
+ de_name = (struct ATTR_FILE_NAME *)(de + 1);
|
|
Kmods SIG |
d83023 |
+ /* Fill duplicate info. */
|
|
Kmods SIG |
d83023 |
+ de_name->dup.cr_time = de_name->dup.m_time = de_name->dup.c_time =
|
|
Kmods SIG |
d83023 |
+ de_name->dup.a_time = kernel2nt(&inode->i_ctime);
|
|
Kmods SIG |
d83023 |
+ de_name->dup.alloc_size = de_name->dup.data_size =
|
|
Kmods SIG |
d83023 |
+ cpu_to_le64(inode->i_size);
|
|
Kmods SIG |
d83023 |
+ de_name->dup.fa = ni->std_fa;
|
|
Kmods SIG |
d83023 |
+ de_name->dup.ea_size = de_name->dup.reparse = 0;
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
+ err = ni_add_name(ntfs_i(d_inode(dentry->d_parent)), ni, de);
|
|
Kmods SIG |
d83023 |
out:
|
|
Kmods SIG |
d83023 |
- __putname(new_de);
|
|
Kmods SIG |
d83023 |
+ __putname(de);
|
|
Kmods SIG |
d83023 |
return err;
|
|
Kmods SIG |
d83023 |
}
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
@@ -1713,113 +1685,56 @@ int ntfs_link_inode(struct inode *inode, struct dentry *dentry)
|
|
Kmods SIG |
d83023 |
int ntfs_unlink_inode(struct inode *dir, const struct dentry *dentry)
|
|
Kmods SIG |
d83023 |
{
|
|
Kmods SIG |
d83023 |
int err;
|
|
Kmods SIG |
d83023 |
- struct super_block *sb = dir->i_sb;
|
|
Kmods SIG |
d83023 |
- struct ntfs_sb_info *sbi = sb->s_fs_info;
|
|
Kmods SIG |
d83023 |
+ struct ntfs_sb_info *sbi = dir->i_sb->s_fs_info;
|
|
Kmods SIG |
d83023 |
struct inode *inode = d_inode(dentry);
|
|
Kmods SIG |
d83023 |
struct ntfs_inode *ni = ntfs_i(inode);
|
|
Kmods SIG |
d83023 |
- const struct qstr *name = &dentry->d_name;
|
|
Kmods SIG |
d83023 |
struct ntfs_inode *dir_ni = ntfs_i(dir);
|
|
Kmods SIG |
d83023 |
- struct ntfs_index *indx = &dir_ni->dir;
|
|
Kmods SIG |
d83023 |
- struct cpu_str *uni = NULL;
|
|
Kmods SIG |
d83023 |
- struct ATTR_FILE_NAME *fname;
|
|
Kmods SIG |
d83023 |
- u8 name_type;
|
|
Kmods SIG |
d83023 |
- struct ATTR_LIST_ENTRY *le;
|
|
Kmods SIG |
d83023 |
- struct MFT_REF ref;
|
|
Kmods SIG |
d83023 |
- bool is_dir = S_ISDIR(inode->i_mode);
|
|
Kmods SIG |
d83023 |
- struct INDEX_ROOT *dir_root;
|
|
Kmods SIG |
d83023 |
+ struct NTFS_DE *de, *de2 = NULL;
|
|
Kmods SIG |
d83023 |
+ int undo_remove;
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
- dir_root = indx_get_root(indx, dir_ni, NULL, NULL);
|
|
Kmods SIG |
d83023 |
- if (!dir_root)
|
|
Kmods SIG |
d83023 |
+ if (ntfs_is_meta_file(sbi, ni->mi.rno))
|
|
Kmods SIG |
d83023 |
return -EINVAL;
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
+ /* Allocate PATH_MAX bytes. */
|
|
Kmods SIG |
d83023 |
+ de = __getname();
|
|
Kmods SIG |
d83023 |
+ if (!de)
|
|
Kmods SIG |
d83023 |
+ return -ENOMEM;
|
|
Kmods SIG |
d83023 |
+
|
|
Kmods SIG |
d83023 |
ni_lock(ni);
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
- if (is_dir && !dir_is_empty(inode)) {
|
|
Kmods SIG |
d83023 |
+ if (S_ISDIR(inode->i_mode) && !dir_is_empty(inode)) {
|
|
Kmods SIG |
d83023 |
err = -ENOTEMPTY;
|
|
Kmods SIG |
d83023 |
- goto out1;
|
|
Kmods SIG |
d83023 |
- }
|
|
Kmods SIG |
d83023 |
-
|
|
Kmods SIG |
d83023 |
- if (ntfs_is_meta_file(sbi, inode->i_ino)) {
|
|
Kmods SIG |
d83023 |
- err = -EINVAL;
|
|
Kmods SIG |
d83023 |
- goto out1;
|
|
Kmods SIG |
d83023 |
- }
|
|
Kmods SIG |
d83023 |
-
|
|
Kmods SIG |
d83023 |
- /* Allocate PATH_MAX bytes. */
|
|
Kmods SIG |
d83023 |
- uni = __getname();
|
|
Kmods SIG |
d83023 |
- if (!uni) {
|
|
Kmods SIG |
d83023 |
- err = -ENOMEM;
|
|
Kmods SIG |
d83023 |
- goto out1;
|
|
Kmods SIG |
d83023 |
+ goto out;
|
|
Kmods SIG |
d83023 |
}
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
- /* Convert input string to unicode. */
|
|
Kmods SIG |
d83023 |
- err = ntfs_nls_to_utf16(sbi, name->name, name->len, uni, NTFS_NAME_LEN,
|
|
Kmods SIG |
d83023 |
- UTF16_HOST_ENDIAN);
|
|
Kmods SIG |
d83023 |
+ err = fill_name_de(sbi, de, &dentry->d_name, NULL);
|
|
Kmods SIG |
d83023 |
if (err < 0)
|
|
Kmods SIG |
d83023 |
- goto out2;
|
|
Kmods SIG |
d83023 |
-
|
|
Kmods SIG |
d83023 |
- /* Mark rw ntfs as dirty. It will be cleared at umount. */
|
|
Kmods SIG |
d83023 |
- ntfs_set_state(sbi, NTFS_DIRTY_DIRTY);
|
|
Kmods SIG |
d83023 |
-
|
|
Kmods SIG |
d83023 |
- /* Find name in record. */
|
|
Kmods SIG |
d83023 |
- mi_get_ref(&dir_ni->mi, &ref;;
|
|
Kmods SIG |
d83023 |
-
|
|
Kmods SIG |
d83023 |
- le = NULL;
|
|
Kmods SIG |
d83023 |
- fname = ni_fname_name(ni, uni, &ref, &le);
|
|
Kmods SIG |
d83023 |
- if (!fname) {
|
|
Kmods SIG |
d83023 |
- err = -ENOENT;
|
|
Kmods SIG |
d83023 |
- goto out3;
|
|
Kmods SIG |
d83023 |
- }
|
|
Kmods SIG |
d83023 |
-
|
|
Kmods SIG |
d83023 |
- name_type = paired_name(fname->type);
|
|
Kmods SIG |
d83023 |
-
|
|
Kmods SIG |
d83023 |
- err = indx_delete_entry(indx, dir_ni, fname, fname_full_size(fname),
|
|
Kmods SIG |
d83023 |
- sbi);
|
|
Kmods SIG |
d83023 |
- if (err)
|
|
Kmods SIG |
d83023 |
- goto out3;
|
|
Kmods SIG |
d83023 |
-
|
|
Kmods SIG |
d83023 |
- /* Then remove name from MFT. */
|
|
Kmods SIG |
d83023 |
- ni_remove_attr_le(ni, attr_from_name(fname), le);
|
|
Kmods SIG |
d83023 |
-
|
|
Kmods SIG |
d83023 |
- le16_add_cpu(&ni->mi.mrec->hard_links, -1);
|
|
Kmods SIG |
d83023 |
- ni->mi.dirty = true;
|
|
Kmods SIG |
d83023 |
-
|
|
Kmods SIG |
d83023 |
- if (name_type != FILE_NAME_POSIX) {
|
|
Kmods SIG |
d83023 |
- /* Now we should delete name by type. */
|
|
Kmods SIG |
d83023 |
- fname = ni_fname_type(ni, name_type, &le);
|
|
Kmods SIG |
d83023 |
- if (fname) {
|
|
Kmods SIG |
d83023 |
- err = indx_delete_entry(indx, dir_ni, fname,
|
|
Kmods SIG |
d83023 |
- fname_full_size(fname), sbi);
|
|
Kmods SIG |
d83023 |
- if (err)
|
|
Kmods SIG |
d83023 |
- goto out3;
|
|
Kmods SIG |
d83023 |
+ goto out;
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
- ni_remove_attr_le(ni, attr_from_name(fname), le);
|
|
Kmods SIG |
d83023 |
+ undo_remove = 0;
|
|
Kmods SIG |
d83023 |
+ err = ni_remove_name(dir_ni, ni, de, &de2, &undo_remove);
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
- le16_add_cpu(&ni->mi.mrec->hard_links, -1);
|
|
Kmods SIG |
d83023 |
- }
|
|
Kmods SIG |
d83023 |
- }
|
|
Kmods SIG |
d83023 |
-out3:
|
|
Kmods SIG |
d83023 |
- switch (err) {
|
|
Kmods SIG |
d83023 |
- case 0:
|
|
Kmods SIG |
d83023 |
+ if (!err) {
|
|
Kmods SIG |
d83023 |
drop_nlink(inode);
|
|
Kmods SIG |
d83023 |
- break;
|
|
Kmods SIG |
d83023 |
- case -ENOTEMPTY:
|
|
Kmods SIG |
d83023 |
- case -ENOSPC:
|
|
Kmods SIG |
d83023 |
- case -EROFS:
|
|
Kmods SIG |
d83023 |
- break;
|
|
Kmods SIG |
d83023 |
- default:
|
|
Kmods SIG |
d83023 |
+ dir->i_mtime = dir->i_ctime = current_time(dir);
|
|
Kmods SIG |
d83023 |
+ mark_inode_dirty(dir);
|
|
Kmods SIG |
d83023 |
+ inode->i_ctime = dir->i_ctime;
|
|
Kmods SIG |
d83023 |
+ if (inode->i_nlink)
|
|
Kmods SIG |
d83023 |
+ mark_inode_dirty(inode);
|
|
Kmods SIG |
d83023 |
+ } else if (!ni_remove_name_undo(dir_ni, ni, de, de2, undo_remove)) {
|
|
Kmods SIG |
d83023 |
make_bad_inode(inode);
|
|
Kmods SIG |
d83023 |
+ ntfs_inode_err(inode, "failed to undo unlink");
|
|
Kmods SIG |
d83023 |
+ ntfs_set_state(sbi, NTFS_DIRTY_ERROR);
|
|
Kmods SIG |
d83023 |
+ } else {
|
|
Kmods SIG |
d83023 |
+ if (ni_is_dirty(dir))
|
|
Kmods SIG |
d83023 |
+ mark_inode_dirty(dir);
|
|
Kmods SIG |
d83023 |
+ if (ni_is_dirty(inode))
|
|
Kmods SIG |
d83023 |
+ mark_inode_dirty(inode);
|
|
Kmods SIG |
d83023 |
}
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
- dir->i_mtime = dir->i_ctime = current_time(dir);
|
|
Kmods SIG |
d83023 |
- mark_inode_dirty(dir);
|
|
Kmods SIG |
d83023 |
- inode->i_ctime = dir->i_ctime;
|
|
Kmods SIG |
d83023 |
- if (inode->i_nlink)
|
|
Kmods SIG |
d83023 |
- mark_inode_dirty(inode);
|
|
Kmods SIG |
d83023 |
-
|
|
Kmods SIG |
d83023 |
-out2:
|
|
Kmods SIG |
d83023 |
- __putname(uni);
|
|
Kmods SIG |
d83023 |
-out1:
|
|
Kmods SIG |
d83023 |
+out:
|
|
Kmods SIG |
d83023 |
ni_unlock(ni);
|
|
Kmods SIG |
d83023 |
+ __putname(de);
|
|
Kmods SIG |
d83023 |
return err;
|
|
Kmods SIG |
d83023 |
}
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
diff --git a/src/namei.c b/src/namei.c
|
|
Kmods SIG |
d83023 |
index f79a399bd015056f320714c91b935afac16eb488..e58415d0713280297df1b7bac30eb17642431fa0 100644
|
|
Kmods SIG |
d83023 |
--- a/src/namei.c
|
|
Kmods SIG |
d83023 |
+++ b/src/namei.c
|
|
Kmods SIG |
d83023 |
@@ -152,12 +152,14 @@ static int ntfs_link(struct dentry *ode, struct inode *dir, struct dentry *de)
|
|
Kmods SIG |
d83023 |
if (inode != dir)
|
|
Kmods SIG |
d83023 |
ni_lock(ni);
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
- dir->i_ctime = dir->i_mtime = inode->i_ctime = current_time(inode);
|
|
Kmods SIG |
d83023 |
inc_nlink(inode);
|
|
Kmods SIG |
d83023 |
ihold(inode);
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
err = ntfs_link_inode(inode, de);
|
|
Kmods SIG |
d83023 |
+
|
|
Kmods SIG |
d83023 |
if (!err) {
|
|
Kmods SIG |
d83023 |
+ dir->i_ctime = dir->i_mtime = inode->i_ctime =
|
|
Kmods SIG |
d83023 |
+ current_time(dir);
|
|
Kmods SIG |
d83023 |
mark_inode_dirty(inode);
|
|
Kmods SIG |
d83023 |
mark_inode_dirty(dir);
|
|
Kmods SIG |
d83023 |
d_instantiate(de, inode);
|
|
Kmods SIG |
d83023 |
@@ -249,25 +251,26 @@ static int ntfs_rmdir(struct inode *dir, struct dentry *dentry)
|
|
Kmods SIG |
d83023 |
/*
|
|
Kmods SIG |
d83023 |
* ntfs_rename - inode_operations::rename
|
|
Kmods SIG |
d83023 |
*/
|
|
Kmods SIG |
d83023 |
-static int ntfs_rename(struct user_namespace *mnt_userns, struct inode *old_dir,
|
|
Kmods SIG |
d83023 |
- struct dentry *old_dentry, struct inode *new_dir,
|
|
Kmods SIG |
d83023 |
+static int ntfs_rename(struct user_namespace *mnt_userns, struct inode *dir,
|
|
Kmods SIG |
d83023 |
+ struct dentry *dentry, struct inode *new_dir,
|
|
Kmods SIG |
d83023 |
struct dentry *new_dentry, u32 flags)
|
|
Kmods SIG |
d83023 |
{
|
|
Kmods SIG |
d83023 |
int err;
|
|
Kmods SIG |
d83023 |
- struct super_block *sb = old_dir->i_sb;
|
|
Kmods SIG |
d83023 |
+ struct super_block *sb = dir->i_sb;
|
|
Kmods SIG |
d83023 |
struct ntfs_sb_info *sbi = sb->s_fs_info;
|
|
Kmods SIG |
d83023 |
- struct ntfs_inode *old_dir_ni = ntfs_i(old_dir);
|
|
Kmods SIG |
d83023 |
+ struct ntfs_inode *dir_ni = ntfs_i(dir);
|
|
Kmods SIG |
d83023 |
struct ntfs_inode *new_dir_ni = ntfs_i(new_dir);
|
|
Kmods SIG |
d83023 |
- struct ntfs_inode *old_ni;
|
|
Kmods SIG |
d83023 |
- struct ATTR_FILE_NAME *old_name, *new_name, *fname;
|
|
Kmods SIG |
d83023 |
- u8 name_type;
|
|
Kmods SIG |
d83023 |
- bool is_same;
|
|
Kmods SIG |
d83023 |
- struct inode *old_inode, *new_inode;
|
|
Kmods SIG |
d83023 |
- struct NTFS_DE *old_de, *new_de;
|
|
Kmods SIG |
d83023 |
- struct ATTRIB *attr;
|
|
Kmods SIG |
d83023 |
- struct ATTR_LIST_ENTRY *le;
|
|
Kmods SIG |
d83023 |
- u16 new_de_key_size;
|
|
Kmods SIG |
d83023 |
-
|
|
Kmods SIG |
d83023 |
+ struct inode *inode = d_inode(dentry);
|
|
Kmods SIG |
d83023 |
+ struct ntfs_inode *ni = ntfs_i(inode);
|
|
Kmods SIG |
d83023 |
+ struct inode *new_inode = d_inode(new_dentry);
|
|
Kmods SIG |
d83023 |
+ struct NTFS_DE *de, *new_de;
|
|
Kmods SIG |
d83023 |
+ bool is_same, is_bad;
|
|
Kmods SIG |
d83023 |
+ /*
|
|
Kmods SIG |
d83023 |
+ * de - memory of PATH_MAX bytes:
|
|
Kmods SIG |
d83023 |
+ * [0-1024) - original name (dentry->d_name)
|
|
Kmods SIG |
d83023 |
+ * [1024-2048) - paired to original name, usually DOS variant of dentry->d_name
|
|
Kmods SIG |
d83023 |
+ * [2048-3072) - new name (new_dentry->d_name)
|
|
Kmods SIG |
d83023 |
+ */
|
|
Kmods SIG |
d83023 |
static_assert(SIZEOF_ATTRIBUTE_FILENAME_MAX + SIZEOF_RESIDENT < 1024);
|
|
Kmods SIG |
d83023 |
static_assert(SIZEOF_ATTRIBUTE_FILENAME_MAX + sizeof(struct NTFS_DE) <
|
|
Kmods SIG |
d83023 |
1024);
|
|
Kmods SIG |
d83023 |
@@ -276,24 +279,18 @@ static int ntfs_rename(struct user_namespace *mnt_userns, struct inode *old_dir,
|
|
Kmods SIG |
d83023 |
if (flags & ~RENAME_NOREPLACE)
|
|
Kmods SIG |
d83023 |
return -EINVAL;
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
- old_inode = d_inode(old_dentry);
|
|
Kmods SIG |
d83023 |
- new_inode = d_inode(new_dentry);
|
|
Kmods SIG |
d83023 |
-
|
|
Kmods SIG |
d83023 |
- old_ni = ntfs_i(old_inode);
|
|
Kmods SIG |
d83023 |
+ is_same = dentry->d_name.len == new_dentry->d_name.len &&
|
|
Kmods SIG |
d83023 |
+ !memcmp(dentry->d_name.name, new_dentry->d_name.name,
|
|
Kmods SIG |
d83023 |
+ dentry->d_name.len);
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
- is_same = old_dentry->d_name.len == new_dentry->d_name.len &&
|
|
Kmods SIG |
d83023 |
- !memcmp(old_dentry->d_name.name, new_dentry->d_name.name,
|
|
Kmods SIG |
d83023 |
- old_dentry->d_name.len);
|
|
Kmods SIG |
d83023 |
-
|
|
Kmods SIG |
d83023 |
- if (is_same && old_dir == new_dir) {
|
|
Kmods SIG |
d83023 |
+ if (is_same && dir == new_dir) {
|
|
Kmods SIG |
d83023 |
/* Nothing to do. */
|
|
Kmods SIG |
d83023 |
- err = 0;
|
|
Kmods SIG |
d83023 |
- goto out;
|
|
Kmods SIG |
d83023 |
+ return 0;
|
|
Kmods SIG |
d83023 |
}
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
- if (ntfs_is_meta_file(sbi, old_inode->i_ino)) {
|
|
Kmods SIG |
d83023 |
- err = -EINVAL;
|
|
Kmods SIG |
d83023 |
- goto out;
|
|
Kmods SIG |
d83023 |
+ if (ntfs_is_meta_file(sbi, inode->i_ino)) {
|
|
Kmods SIG |
d83023 |
+ /* Should we print an error? */
|
|
Kmods SIG |
d83023 |
+ return -EINVAL;
|
|
Kmods SIG |
d83023 |
}
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
if (new_inode) {
|
|
Kmods SIG |
d83023 |
@@ -304,168 +301,61 @@ static int ntfs_rename(struct user_namespace *mnt_userns, struct inode *old_dir,
|
|
Kmods SIG |
d83023 |
ni_unlock(new_dir_ni);
|
|
Kmods SIG |
d83023 |
dput(new_dentry);
|
|
Kmods SIG |
d83023 |
if (err)
|
|
Kmods SIG |
d83023 |
- goto out;
|
|
Kmods SIG |
d83023 |
+ return err;
|
|
Kmods SIG |
d83023 |
}
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
/* Allocate PATH_MAX bytes. */
|
|
Kmods SIG |
d83023 |
- old_de = __getname();
|
|
Kmods SIG |
d83023 |
- if (!old_de) {
|
|
Kmods SIG |
d83023 |
- err = -ENOMEM;
|
|
Kmods SIG |
d83023 |
- goto out;
|
|
Kmods SIG |
d83023 |
- }
|
|
Kmods SIG |
d83023 |
+ de = __getname();
|
|
Kmods SIG |
d83023 |
+ if (!de)
|
|
Kmods SIG |
d83023 |
+ return -ENOMEM;
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
- err = fill_name_de(sbi, old_de, &old_dentry->d_name, NULL);
|
|
Kmods SIG |
d83023 |
+ /* Translate dentry->d_name into unicode form. */
|
|
Kmods SIG |
d83023 |
+ err = fill_name_de(sbi, de, &dentry->d_name, NULL);
|
|
Kmods SIG |
d83023 |
if (err < 0)
|
|
Kmods SIG |
d83023 |
- goto out1;
|
|
Kmods SIG |
d83023 |
-
|
|
Kmods SIG |
d83023 |
- old_name = (struct ATTR_FILE_NAME *)(old_de + 1);
|
|
Kmods SIG |
d83023 |
+ goto out;
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
if (is_same) {
|
|
Kmods SIG |
d83023 |
- new_de = old_de;
|
|
Kmods SIG |
d83023 |
+ /* Reuse 'de'. */
|
|
Kmods SIG |
d83023 |
+ new_de = de;
|
|
Kmods SIG |
d83023 |
} else {
|
|
Kmods SIG |
d83023 |
- new_de = Add2Ptr(old_de, 1024);
|
|
Kmods SIG |
d83023 |
+ /* Translate new_dentry->d_name into unicode form. */
|
|
Kmods SIG |
d83023 |
+ new_de = Add2Ptr(de, 2048);
|
|
Kmods SIG |
d83023 |
err = fill_name_de(sbi, new_de, &new_dentry->d_name, NULL);
|
|
Kmods SIG |
d83023 |
if (err < 0)
|
|
Kmods SIG |
d83023 |
- goto out1;
|
|
Kmods SIG |
d83023 |
- }
|
|
Kmods SIG |
d83023 |
-
|
|
Kmods SIG |
d83023 |
- ni_lock_dir(old_dir_ni);
|
|
Kmods SIG |
d83023 |
- ni_lock(old_ni);
|
|
Kmods SIG |
d83023 |
-
|
|
Kmods SIG |
d83023 |
- mi_get_ref(&old_dir_ni->mi, &old_name->home);
|
|
Kmods SIG |
d83023 |
-
|
|
Kmods SIG |
d83023 |
- /* Get pointer to file_name in MFT. */
|
|
Kmods SIG |
d83023 |
- fname = ni_fname_name(old_ni, (struct cpu_str *)&old_name->name_len,
|
|
Kmods SIG |
d83023 |
- &old_name->home, &le);
|
|
Kmods SIG |
d83023 |
- if (!fname) {
|
|
Kmods SIG |
d83023 |
- err = -EINVAL;
|
|
Kmods SIG |
d83023 |
- goto out2;
|
|
Kmods SIG |
d83023 |
+ goto out;
|
|
Kmods SIG |
d83023 |
}
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
- /* Copy fname info from record into new fname. */
|
|
Kmods SIG |
d83023 |
- new_name = (struct ATTR_FILE_NAME *)(new_de + 1);
|
|
Kmods SIG |
d83023 |
- memcpy(&new_name->dup, &fname->dup, sizeof(fname->dup));
|
|
Kmods SIG |
d83023 |
-
|
|
Kmods SIG |
d83023 |
- name_type = paired_name(fname->type);
|
|
Kmods SIG |
d83023 |
-
|
|
Kmods SIG |
d83023 |
- /* Remove first name from directory. */
|
|
Kmods SIG |
d83023 |
- err = indx_delete_entry(&old_dir_ni->dir, old_dir_ni, old_de + 1,
|
|
Kmods SIG |
d83023 |
- le16_to_cpu(old_de->key_size), sbi);
|
|
Kmods SIG |
d83023 |
- if (err)
|
|
Kmods SIG |
d83023 |
- goto out3;
|
|
Kmods SIG |
d83023 |
-
|
|
Kmods SIG |
d83023 |
- /* Remove first name from MFT. */
|
|
Kmods SIG |
d83023 |
- err = ni_remove_attr_le(old_ni, attr_from_name(fname), le);
|
|
Kmods SIG |
d83023 |
- if (err)
|
|
Kmods SIG |
d83023 |
- goto out4;
|
|
Kmods SIG |
d83023 |
-
|
|
Kmods SIG |
d83023 |
- le16_add_cpu(&old_ni->mi.mrec->hard_links, -1);
|
|
Kmods SIG |
d83023 |
- old_ni->mi.dirty = true;
|
|
Kmods SIG |
d83023 |
-
|
|
Kmods SIG |
d83023 |
- if (name_type != FILE_NAME_POSIX) {
|
|
Kmods SIG |
d83023 |
- /* Get paired name. */
|
|
Kmods SIG |
d83023 |
- fname = ni_fname_type(old_ni, name_type, &le);
|
|
Kmods SIG |
d83023 |
- if (fname) {
|
|
Kmods SIG |
d83023 |
- /* Remove second name from directory. */
|
|
Kmods SIG |
d83023 |
- err = indx_delete_entry(&old_dir_ni->dir, old_dir_ni,
|
|
Kmods SIG |
d83023 |
- fname, fname_full_size(fname),
|
|
Kmods SIG |
d83023 |
- sbi);
|
|
Kmods SIG |
d83023 |
- if (err)
|
|
Kmods SIG |
d83023 |
- goto out5;
|
|
Kmods SIG |
d83023 |
-
|
|
Kmods SIG |
d83023 |
- /* Remove second name from MFT. */
|
|
Kmods SIG |
d83023 |
- err = ni_remove_attr_le(old_ni, attr_from_name(fname),
|
|
Kmods SIG |
d83023 |
- le);
|
|
Kmods SIG |
d83023 |
- if (err)
|
|
Kmods SIG |
d83023 |
- goto out6;
|
|
Kmods SIG |
d83023 |
-
|
|
Kmods SIG |
d83023 |
- le16_add_cpu(&old_ni->mi.mrec->hard_links, -1);
|
|
Kmods SIG |
d83023 |
- old_ni->mi.dirty = true;
|
|
Kmods SIG |
d83023 |
+ ni_lock_dir(dir_ni);
|
|
Kmods SIG |
d83023 |
+ ni_lock(ni);
|
|
Kmods SIG |
d83023 |
+
|
|
Kmods SIG |
d83023 |
+ is_bad = false;
|
|
Kmods SIG |
d83023 |
+ err = ni_rename(dir_ni, new_dir_ni, ni, de, new_de, &is_bad);
|
|
Kmods SIG |
d83023 |
+ if (is_bad) {
|
|
Kmods SIG |
d83023 |
+ /* Restore after failed rename failed too. */
|
|
Kmods SIG |
d83023 |
+ make_bad_inode(inode);
|
|
Kmods SIG |
d83023 |
+ ntfs_inode_err(inode, "failed to undo rename");
|
|
Kmods SIG |
d83023 |
+ ntfs_set_state(sbi, NTFS_DIRTY_ERROR);
|
|
Kmods SIG |
d83023 |
+ } else if (!err) {
|
|
Kmods SIG |
d83023 |
+ inode->i_ctime = dir->i_ctime = dir->i_mtime =
|
|
Kmods SIG |
d83023 |
+ current_time(dir);
|
|
Kmods SIG |
d83023 |
+ mark_inode_dirty(inode);
|
|
Kmods SIG |
d83023 |
+ mark_inode_dirty(dir);
|
|
Kmods SIG |
d83023 |
+ if (dir != new_dir) {
|
|
Kmods SIG |
d83023 |
+ new_dir->i_mtime = new_dir->i_ctime = dir->i_ctime;
|
|
Kmods SIG |
d83023 |
+ mark_inode_dirty(new_dir);
|
|
Kmods SIG |
d83023 |
}
|
|
Kmods SIG |
d83023 |
- }
|
|
Kmods SIG |
d83023 |
-
|
|
Kmods SIG |
d83023 |
- /* Add new name. */
|
|
Kmods SIG |
d83023 |
- mi_get_ref(&old_ni->mi, &new_de->ref);
|
|
Kmods SIG |
d83023 |
- mi_get_ref(&ntfs_i(new_dir)->mi, &new_name->home);
|
|
Kmods SIG |
d83023 |
-
|
|
Kmods SIG |
d83023 |
- new_de_key_size = le16_to_cpu(new_de->key_size);
|
|
Kmods SIG |
d83023 |
-
|
|
Kmods SIG |
d83023 |
- /* Insert new name in MFT. */
|
|
Kmods SIG |
d83023 |
- err = ni_insert_resident(old_ni, new_de_key_size, ATTR_NAME, NULL, 0,
|
|
Kmods SIG |
d83023 |
- &attr, NULL);
|
|
Kmods SIG |
d83023 |
- if (err)
|
|
Kmods SIG |
d83023 |
- goto out7;
|
|
Kmods SIG |
d83023 |
-
|
|
Kmods SIG |
d83023 |
- attr->res.flags = RESIDENT_FLAG_INDEXED;
|
|
Kmods SIG |
d83023 |
-
|
|
Kmods SIG |
d83023 |
- memcpy(Add2Ptr(attr, SIZEOF_RESIDENT), new_name, new_de_key_size);
|
|
Kmods SIG |
d83023 |
-
|
|
Kmods SIG |
d83023 |
- le16_add_cpu(&old_ni->mi.mrec->hard_links, 1);
|
|
Kmods SIG |
d83023 |
- old_ni->mi.dirty = true;
|
|
Kmods SIG |
d83023 |
-
|
|
Kmods SIG |
d83023 |
- /* Insert new name in directory. */
|
|
Kmods SIG |
d83023 |
- err = indx_insert_entry(&new_dir_ni->dir, new_dir_ni, new_de, sbi,
|
|
Kmods SIG |
d83023 |
- NULL);
|
|
Kmods SIG |
d83023 |
- if (err)
|
|
Kmods SIG |
d83023 |
- goto out8;
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
- if (IS_DIRSYNC(new_dir))
|
|
Kmods SIG |
d83023 |
- err = ntfs_sync_inode(old_inode);
|
|
Kmods SIG |
d83023 |
- else
|
|
Kmods SIG |
d83023 |
- mark_inode_dirty(old_inode);
|
|
Kmods SIG |
d83023 |
+ if (IS_DIRSYNC(dir))
|
|
Kmods SIG |
d83023 |
+ ntfs_sync_inode(dir);
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
- old_dir->i_ctime = old_dir->i_mtime = current_time(old_dir);
|
|
Kmods SIG |
d83023 |
- if (IS_DIRSYNC(old_dir))
|
|
Kmods SIG |
d83023 |
- (void)ntfs_sync_inode(old_dir);
|
|
Kmods SIG |
d83023 |
- else
|
|
Kmods SIG |
d83023 |
- mark_inode_dirty(old_dir);
|
|
Kmods SIG |
d83023 |
-
|
|
Kmods SIG |
d83023 |
- if (old_dir != new_dir) {
|
|
Kmods SIG |
d83023 |
- new_dir->i_mtime = new_dir->i_ctime = old_dir->i_ctime;
|
|
Kmods SIG |
d83023 |
- mark_inode_dirty(new_dir);
|
|
Kmods SIG |
d83023 |
- }
|
|
Kmods SIG |
d83023 |
-
|
|
Kmods SIG |
d83023 |
- if (old_inode) {
|
|
Kmods SIG |
d83023 |
- old_inode->i_ctime = old_dir->i_ctime;
|
|
Kmods SIG |
d83023 |
- mark_inode_dirty(old_inode);
|
|
Kmods SIG |
d83023 |
+ if (IS_DIRSYNC(new_dir))
|
|
Kmods SIG |
d83023 |
+ ntfs_sync_inode(inode);
|
|
Kmods SIG |
d83023 |
}
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
- err = 0;
|
|
Kmods SIG |
d83023 |
- /* Normal way* */
|
|
Kmods SIG |
d83023 |
- goto out2;
|
|
Kmods SIG |
d83023 |
-
|
|
Kmods SIG |
d83023 |
-out8:
|
|
Kmods SIG |
d83023 |
- /* undo
|
|
Kmods SIG |
d83023 |
- * ni_insert_resident(old_ni, new_de_key_size, ATTR_NAME, NULL, 0,
|
|
Kmods SIG |
d83023 |
- * &attr, NULL);
|
|
Kmods SIG |
d83023 |
- */
|
|
Kmods SIG |
d83023 |
- mi_remove_attr(&old_ni->mi, attr);
|
|
Kmods SIG |
d83023 |
-out7:
|
|
Kmods SIG |
d83023 |
- /* undo
|
|
Kmods SIG |
d83023 |
- * ni_remove_attr_le(old_ni, attr_from_name(fname), le);
|
|
Kmods SIG |
d83023 |
- */
|
|
Kmods SIG |
d83023 |
-out6:
|
|
Kmods SIG |
d83023 |
- /* undo
|
|
Kmods SIG |
d83023 |
- * indx_delete_entry(&old_dir_ni->dir, old_dir_ni,
|
|
Kmods SIG |
d83023 |
- * fname, fname_full_size(fname),
|
|
Kmods SIG |
d83023 |
- * sbi);
|
|
Kmods SIG |
d83023 |
- */
|
|
Kmods SIG |
d83023 |
-out5:
|
|
Kmods SIG |
d83023 |
- /* undo
|
|
Kmods SIG |
d83023 |
- * ni_remove_attr_le(old_ni, attr_from_name(fname), le);
|
|
Kmods SIG |
d83023 |
- */
|
|
Kmods SIG |
d83023 |
-out4:
|
|
Kmods SIG |
d83023 |
- /* undo:
|
|
Kmods SIG |
d83023 |
- * indx_delete_entry(&old_dir_ni->dir, old_dir_ni, old_de + 1,
|
|
Kmods SIG |
d83023 |
- * old_de->key_size, NULL);
|
|
Kmods SIG |
d83023 |
- */
|
|
Kmods SIG |
d83023 |
-out3:
|
|
Kmods SIG |
d83023 |
-out2:
|
|
Kmods SIG |
d83023 |
- ni_unlock(old_ni);
|
|
Kmods SIG |
d83023 |
- ni_unlock(old_dir_ni);
|
|
Kmods SIG |
d83023 |
-out1:
|
|
Kmods SIG |
d83023 |
- __putname(old_de);
|
|
Kmods SIG |
d83023 |
+ ni_unlock(ni);
|
|
Kmods SIG |
d83023 |
+ ni_unlock(dir_ni);
|
|
Kmods SIG |
d83023 |
out:
|
|
Kmods SIG |
d83023 |
+ __putname(de);
|
|
Kmods SIG |
d83023 |
return err;
|
|
Kmods SIG |
d83023 |
}
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
diff --git a/src/ntfs_fs.h b/src/ntfs_fs.h
|
|
Kmods SIG |
d83023 |
index 64ef92e16363c4973be6438efdeea0663ce10e84..f9436cbbc347b617b458bb21d6c7229b467ca289 100644
|
|
Kmods SIG |
d83023 |
--- a/src/ntfs_fs.h
|
|
Kmods SIG |
d83023 |
+++ b/src/ntfs_fs.h
|
|
Kmods SIG |
d83023 |
@@ -478,7 +478,7 @@ struct ATTR_STD_INFO *ni_std(struct ntfs_inode *ni);
|
|
Kmods SIG |
d83023 |
struct ATTR_STD_INFO5 *ni_std5(struct ntfs_inode *ni);
|
|
Kmods SIG |
d83023 |
void ni_clear(struct ntfs_inode *ni);
|
|
Kmods SIG |
d83023 |
int ni_load_mi_ex(struct ntfs_inode *ni, CLST rno, struct mft_inode **mi);
|
|
Kmods SIG |
d83023 |
-int ni_load_mi(struct ntfs_inode *ni, struct ATTR_LIST_ENTRY *le,
|
|
Kmods SIG |
d83023 |
+int ni_load_mi(struct ntfs_inode *ni, const struct ATTR_LIST_ENTRY *le,
|
|
Kmods SIG |
d83023 |
struct mft_inode **mi);
|
|
Kmods SIG |
d83023 |
struct ATTRIB *ni_find_attr(struct ntfs_inode *ni, struct ATTRIB *attr,
|
|
Kmods SIG |
d83023 |
struct ATTR_LIST_ENTRY **entry_o,
|
|
Kmods SIG |
d83023 |
@@ -505,15 +505,18 @@ int ni_insert_nonresident(struct ntfs_inode *ni, enum ATTR_TYPE type,
|
|
Kmods SIG |
d83023 |
struct mft_inode **mi);
|
|
Kmods SIG |
d83023 |
int ni_insert_resident(struct ntfs_inode *ni, u32 data_size,
|
|
Kmods SIG |
d83023 |
enum ATTR_TYPE type, const __le16 *name, u8 name_len,
|
|
Kmods SIG |
d83023 |
- struct ATTRIB **new_attr, struct mft_inode **mi);
|
|
Kmods SIG |
d83023 |
-int ni_remove_attr_le(struct ntfs_inode *ni, struct ATTRIB *attr,
|
|
Kmods SIG |
d83023 |
- struct ATTR_LIST_ENTRY *le);
|
|
Kmods SIG |
d83023 |
+ struct ATTRIB **new_attr, struct mft_inode **mi,
|
|
Kmods SIG |
d83023 |
+ struct ATTR_LIST_ENTRY **le);
|
|
Kmods SIG |
d83023 |
+void ni_remove_attr_le(struct ntfs_inode *ni, struct ATTRIB *attr,
|
|
Kmods SIG |
d83023 |
+ struct mft_inode *mi, struct ATTR_LIST_ENTRY *le);
|
|
Kmods SIG |
d83023 |
int ni_delete_all(struct ntfs_inode *ni);
|
|
Kmods SIG |
d83023 |
struct ATTR_FILE_NAME *ni_fname_name(struct ntfs_inode *ni,
|
|
Kmods SIG |
d83023 |
const struct cpu_str *uni,
|
|
Kmods SIG |
d83023 |
const struct MFT_REF *home,
|
|
Kmods SIG |
d83023 |
+ struct mft_inode **mi,
|
|
Kmods SIG |
d83023 |
struct ATTR_LIST_ENTRY **entry);
|
|
Kmods SIG |
d83023 |
struct ATTR_FILE_NAME *ni_fname_type(struct ntfs_inode *ni, u8 name_type,
|
|
Kmods SIG |
d83023 |
+ struct mft_inode **mi,
|
|
Kmods SIG |
d83023 |
struct ATTR_LIST_ENTRY **entry);
|
|
Kmods SIG |
d83023 |
int ni_new_attr_flags(struct ntfs_inode *ni, enum FILE_ATTRIBUTE new_fa);
|
|
Kmods SIG |
d83023 |
enum REPARSE_SIGN ni_parse_reparse(struct ntfs_inode *ni, struct ATTRIB *attr,
|
|
Kmods SIG |
d83023 |
@@ -528,6 +531,21 @@ int ni_read_frame(struct ntfs_inode *ni, u64 frame_vbo, struct page **pages,
|
|
Kmods SIG |
d83023 |
u32 pages_per_frame);
|
|
Kmods SIG |
d83023 |
int ni_write_frame(struct ntfs_inode *ni, struct page **pages,
|
|
Kmods SIG |
d83023 |
u32 pages_per_frame);
|
|
Kmods SIG |
d83023 |
+int ni_remove_name(struct ntfs_inode *dir_ni, struct ntfs_inode *ni,
|
|
Kmods SIG |
d83023 |
+ struct NTFS_DE *de, struct NTFS_DE **de2, int *undo_step);
|
|
Kmods SIG |
d83023 |
+
|
|
Kmods SIG |
d83023 |
+bool ni_remove_name_undo(struct ntfs_inode *dir_ni, struct ntfs_inode *ni,
|
|
Kmods SIG |
d83023 |
+ struct NTFS_DE *de, struct NTFS_DE *de2,
|
|
Kmods SIG |
d83023 |
+ int undo_step);
|
|
Kmods SIG |
d83023 |
+
|
|
Kmods SIG |
d83023 |
+int ni_add_name(struct ntfs_inode *dir_ni, struct ntfs_inode *ni,
|
|
Kmods SIG |
d83023 |
+ struct NTFS_DE *de);
|
|
Kmods SIG |
d83023 |
+
|
|
Kmods SIG |
d83023 |
+int ni_rename(struct ntfs_inode *dir_ni, struct ntfs_inode *new_dir_ni,
|
|
Kmods SIG |
d83023 |
+ struct ntfs_inode *ni, struct NTFS_DE *de, struct NTFS_DE *new_de,
|
|
Kmods SIG |
d83023 |
+ bool *is_bad);
|
|
Kmods SIG |
d83023 |
+
|
|
Kmods SIG |
d83023 |
+bool ni_is_dirty(struct inode *inode);
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
/* Globals from fslog.c */
|
|
Kmods SIG |
d83023 |
int log_replay(struct ntfs_inode *ni, bool *initialized);
|
|
Kmods SIG |
d83023 |
@@ -631,7 +649,7 @@ int indx_find_raw(struct ntfs_index *indx, struct ntfs_inode *ni,
|
|
Kmods SIG |
d83023 |
size_t *off, struct ntfs_fnd *fnd);
|
|
Kmods SIG |
d83023 |
int indx_insert_entry(struct ntfs_index *indx, struct ntfs_inode *ni,
|
|
Kmods SIG |
d83023 |
const struct NTFS_DE *new_de, const void *param,
|
|
Kmods SIG |
d83023 |
- struct ntfs_fnd *fnd);
|
|
Kmods SIG |
d83023 |
+ struct ntfs_fnd *fnd, bool undo);
|
|
Kmods SIG |
d83023 |
int indx_delete_entry(struct ntfs_index *indx, struct ntfs_inode *ni,
|
|
Kmods SIG |
d83023 |
const void *key, u32 key_len, const void *param);
|
|
Kmods SIG |
d83023 |
int indx_update_dup(struct ntfs_inode *ni, struct ntfs_sb_info *sbi,
|
|
Kmods SIG |
d83023 |
@@ -694,7 +712,8 @@ struct ATTRIB *mi_insert_attr(struct mft_inode *mi, enum ATTR_TYPE type,
|
|
Kmods SIG |
d83023 |
const __le16 *name, u8 name_len, u32 asize,
|
|
Kmods SIG |
d83023 |
u16 name_off);
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
-bool mi_remove_attr(struct mft_inode *mi, struct ATTRIB *attr);
|
|
Kmods SIG |
d83023 |
+bool mi_remove_attr(struct ntfs_inode *ni, struct mft_inode *mi,
|
|
Kmods SIG |
d83023 |
+ struct ATTRIB *attr);
|
|
Kmods SIG |
d83023 |
bool mi_resize_attr(struct mft_inode *mi, struct ATTRIB *attr, int bytes);
|
|
Kmods SIG |
d83023 |
int mi_pack_runs(struct mft_inode *mi, struct ATTRIB *attr,
|
|
Kmods SIG |
d83023 |
struct runs_tree *run, CLST len);
|
|
Kmods SIG |
d83023 |
diff --git a/src/record.c b/src/record.c
|
|
Kmods SIG |
d83023 |
index d48a5e6c5045c5f154f3c1aba4108f458e9676b0..61e3f2fb619f698ffdf5d81ca6f488008002de52 100644
|
|
Kmods SIG |
d83023 |
--- a/src/record.c
|
|
Kmods SIG |
d83023 |
+++ b/src/record.c
|
|
Kmods SIG |
d83023 |
@@ -489,7 +489,8 @@ struct ATTRIB *mi_insert_attr(struct mft_inode *mi, enum ATTR_TYPE type,
|
|
Kmods SIG |
d83023 |
*
|
|
Kmods SIG |
d83023 |
* NOTE: The source attr will point to next attribute.
|
|
Kmods SIG |
d83023 |
*/
|
|
Kmods SIG |
d83023 |
-bool mi_remove_attr(struct mft_inode *mi, struct ATTRIB *attr)
|
|
Kmods SIG |
d83023 |
+bool mi_remove_attr(struct ntfs_inode *ni, struct mft_inode *mi,
|
|
Kmods SIG |
d83023 |
+ struct ATTRIB *attr)
|
|
Kmods SIG |
d83023 |
{
|
|
Kmods SIG |
d83023 |
struct MFT_REC *rec = mi->mrec;
|
|
Kmods SIG |
d83023 |
u32 aoff = PtrOffset(rec, attr);
|
|
Kmods SIG |
d83023 |
@@ -499,6 +500,11 @@ bool mi_remove_attr(struct mft_inode *mi, struct ATTRIB *attr)
|
|
Kmods SIG |
d83023 |
if (aoff + asize > used)
|
|
Kmods SIG |
d83023 |
return false;
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
+ if (ni && is_attr_indexed(attr)) {
|
|
Kmods SIG |
d83023 |
+ le16_add_cpu(&ni->mi.mrec->hard_links, -1);
|
|
Kmods SIG |
d83023 |
+ ni->mi.dirty = true;
|
|
Kmods SIG |
d83023 |
+ }
|
|
Kmods SIG |
d83023 |
+
|
|
Kmods SIG |
d83023 |
used -= asize;
|
|
Kmods SIG |
d83023 |
memmove(attr, Add2Ptr(attr, asize), used - aoff);
|
|
Kmods SIG |
d83023 |
rec->used = cpu_to_le32(used);
|
|
Kmods SIG |
d83023 |
diff --git a/src/xattr.c b/src/xattr.c
|
|
Kmods SIG |
d83023 |
index b4c921e4bc1a1b4bbb1c51ef7cef6677967b8e13..22fd5eb32c5be7f53b3fd8076599f7dbaf84e2cf 100644
|
|
Kmods SIG |
d83023 |
--- a/src/xattr.c
|
|
Kmods SIG |
d83023 |
+++ b/src/xattr.c
|
|
Kmods SIG |
d83023 |
@@ -395,11 +395,13 @@ static noinline int ntfs_set_ea(struct inode *inode, const char *name,
|
|
Kmods SIG |
d83023 |
}
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
err = ni_insert_resident(ni, sizeof(struct EA_INFO),
|
|
Kmods SIG |
d83023 |
- ATTR_EA_INFO, NULL, 0, NULL, NULL);
|
|
Kmods SIG |
d83023 |
+ ATTR_EA_INFO, NULL, 0, NULL, NULL,
|
|
Kmods SIG |
d83023 |
+ NULL);
|
|
Kmods SIG |
d83023 |
if (err)
|
|
Kmods SIG |
d83023 |
goto out;
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
- err = ni_insert_resident(ni, 0, ATTR_EA, NULL, 0, NULL, NULL);
|
|
Kmods SIG |
d83023 |
+ err = ni_insert_resident(ni, 0, ATTR_EA, NULL, 0, NULL, NULL,
|
|
Kmods SIG |
d83023 |
+ NULL);
|
|
Kmods SIG |
d83023 |
if (err)
|
|
Kmods SIG |
d83023 |
goto out;
|
|
Kmods SIG |
d83023 |
}
|
|
Kmods SIG |
d83023 |
@@ -419,9 +421,7 @@ static noinline int ntfs_set_ea(struct inode *inode, const char *name,
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
if (!size) {
|
|
Kmods SIG |
d83023 |
/* Delete xattr, ATTR_EA_INFO */
|
|
Kmods SIG |
d83023 |
- err = ni_remove_attr_le(ni, attr, le);
|
|
Kmods SIG |
d83023 |
- if (err)
|
|
Kmods SIG |
d83023 |
- goto out;
|
|
Kmods SIG |
d83023 |
+ ni_remove_attr_le(ni, attr, mi, le);
|
|
Kmods SIG |
d83023 |
} else {
|
|
Kmods SIG |
d83023 |
p = resident_data_ex(attr, sizeof(struct EA_INFO));
|
|
Kmods SIG |
d83023 |
if (!p) {
|
|
Kmods SIG |
d83023 |
@@ -441,9 +441,7 @@ static noinline int ntfs_set_ea(struct inode *inode, const char *name,
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
if (!size) {
|
|
Kmods SIG |
d83023 |
/* Delete xattr, ATTR_EA */
|
|
Kmods SIG |
d83023 |
- err = ni_remove_attr_le(ni, attr, le);
|
|
Kmods SIG |
d83023 |
- if (err)
|
|
Kmods SIG |
d83023 |
- goto out;
|
|
Kmods SIG |
d83023 |
+ ni_remove_attr_le(ni, attr, mi, le);
|
|
Kmods SIG |
d83023 |
} else if (attr->non_res) {
|
|
Kmods SIG |
d83023 |
err = ntfs_sb_write_run(sbi, &ea_run, 0, ea_all, size);
|
|
Kmods SIG |
d83023 |
if (err)
|
|
Kmods SIG |
d83023 |
@@ -605,8 +603,7 @@ static noinline int ntfs_set_acl_ex(struct user_namespace *mnt_userns,
|
|
Kmods SIG |
d83023 |
goto out;
|
|
Kmods SIG |
d83023 |
}
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
- err = ntfs_set_ea(inode, name, name_len, value, size,
|
|
Kmods SIG |
d83023 |
- acl ? 0 : XATTR_REPLACE, locked);
|
|
Kmods SIG |
d83023 |
+ err = ntfs_set_ea(inode, name, name_len, value, size, 0, locked);
|
|
Kmods SIG |
d83023 |
if (!err)
|
|
Kmods SIG |
d83023 |
set_cached_acl(inode, type, acl);
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
@@ -632,8 +629,10 @@ static int ntfs_xattr_get_acl(struct user_namespace *mnt_userns,
|
|
Kmods SIG |
d83023 |
struct posix_acl *acl;
|
|
Kmods SIG |
d83023 |
int err;
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
- if (!(inode->i_sb->s_flags & SB_POSIXACL))
|
|
Kmods SIG |
d83023 |
+ if (!(inode->i_sb->s_flags & SB_POSIXACL)) {
|
|
Kmods SIG |
d83023 |
+ ntfs_inode_warn(inode, "add mount option \"acl\" to use acl");
|
|
Kmods SIG |
d83023 |
return -EOPNOTSUPP;
|
|
Kmods SIG |
d83023 |
+ }
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
acl = ntfs_get_acl(inode, type);
|
|
Kmods SIG |
d83023 |
if (IS_ERR(acl))
|
|
Kmods SIG |
d83023 |
@@ -655,8 +654,10 @@ static int ntfs_xattr_set_acl(struct user_namespace *mnt_userns,
|
|
Kmods SIG |
d83023 |
struct posix_acl *acl;
|
|
Kmods SIG |
d83023 |
int err;
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
- if (!(inode->i_sb->s_flags & SB_POSIXACL))
|
|
Kmods SIG |
d83023 |
+ if (!(inode->i_sb->s_flags & SB_POSIXACL)) {
|
|
Kmods SIG |
d83023 |
+ ntfs_inode_warn(inode, "add mount option \"acl\" to use acl");
|
|
Kmods SIG |
d83023 |
return -EOPNOTSUPP;
|
|
Kmods SIG |
d83023 |
+ }
|
|
Kmods SIG |
d83023 |
|
|
Kmods SIG |
d83023 |
if (!inode_owner_or_capable(mnt_userns, inode))
|
|
Kmods SIG |
d83023 |
return -EPERM;
|
|
Kmods SIG |
d83023 |
--
|
|
Kmods SIG |
d83023 |
2.31.1
|
|
Kmods SIG |
d83023 |
|