From: Anton Altaparmakov Date: Thu, 8 Sep 2005 19:40:32 +0000 (+0100) Subject: NTFS: Add fs/ntfs/attrib.[hc]::ntfs_resident_attr_value_resize(). X-Git-Tag: v2.6.14-rc1~507 X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0aacceacf35451ffb771ec825555e98c5dce8b01;p=linux-2.6 NTFS: Add fs/ntfs/attrib.[hc]::ntfs_resident_attr_value_resize(). Signed-off-by: Anton Altaparmakov --- diff --git a/fs/ntfs/ChangeLog b/fs/ntfs/ChangeLog index 96224c0207..29841bf822 100644 --- a/fs/ntfs/ChangeLog +++ b/fs/ntfs/ChangeLog @@ -59,6 +59,7 @@ ToDo/Notes: index entry is in the index root, we forgot to set the @ir pointer in the index context. Thanks to Yura Pakhuchiy for finding this bug. - Remove bogus setting of PageError in ntfs_read_compressed_block(). + - Add fs/ntfs/attrib.[hc]::ntfs_resident_attr_value_resize(). 2.1.23 - Implement extension of resident files and make writing safe as well as many bug fixes, cleanups, and enhancements... diff --git a/fs/ntfs/attrib.c b/fs/ntfs/attrib.c index cd0f9e740b..79dda39806 100644 --- a/fs/ntfs/attrib.c +++ b/fs/ntfs/attrib.c @@ -1246,6 +1246,46 @@ int ntfs_attr_record_resize(MFT_RECORD *m, ATTR_RECORD *a, u32 new_size) return 0; } +/** + * ntfs_resident_attr_value_resize - resize the value of a resident attribute + * @m: mft record containing attribute record + * @a: attribute record whose value to resize + * @new_size: new size in bytes to which to resize the attribute value of @a + * + * Resize the value of the attribute @a in the mft record @m to @new_size bytes. + * If the value is made bigger, the newly allocated space is cleared. + * + * Return 0 on success and -errno on error. The following error codes are + * defined: + * -ENOSPC - Not enough space in the mft record @m to perform the resize. + * + * Note: On error, no modifications have been performed whatsoever. + * + * Warning: If you make a record smaller without having copied all the data you + * are interested in the data may be overwritten. + */ +int ntfs_resident_attr_value_resize(MFT_RECORD *m, ATTR_RECORD *a, + const u32 new_size) +{ + u32 old_size; + + /* Resize the resident part of the attribute record. */ + if (ntfs_attr_record_resize(m, a, + le16_to_cpu(a->data.resident.value_offset) + new_size)) + return -ENOSPC; + /* + * The resize succeeded! If we made the attribute value bigger, clear + * the area between the old size and @new_size. + */ + old_size = le32_to_cpu(a->data.resident.value_length); + if (new_size > old_size) + memset((u8*)a + le16_to_cpu(a->data.resident.value_offset) + + old_size, 0, new_size - old_size); + /* Finally update the length of the attribute value. */ + a->data.resident.value_length = cpu_to_le32(new_size); + return 0; +} + /** * ntfs_attr_make_non_resident - convert a resident to a non-resident attribute * @ni: ntfs inode describing the attribute to convert diff --git a/fs/ntfs/attrib.h b/fs/ntfs/attrib.h index 0e4ac6d3c0..0618ed6fd7 100644 --- a/fs/ntfs/attrib.h +++ b/fs/ntfs/attrib.h @@ -99,6 +99,8 @@ extern int ntfs_attr_can_be_resident(const ntfs_volume *vol, const ATTR_TYPE type); extern int ntfs_attr_record_resize(MFT_RECORD *m, ATTR_RECORD *a, u32 new_size); +extern int ntfs_resident_attr_value_resize(MFT_RECORD *m, ATTR_RECORD *a, + const u32 new_size); extern int ntfs_attr_make_non_resident(ntfs_inode *ni);