mirror of
https://git.code.sf.net/p/ntfs-3g/ntfs-3g.git
synced 2024-11-23 10:04:00 +08:00
fix non-resident TXF_DATA creation, despite its AttrDef definition,
which caused Vista and later not being able to access files, volumes (Anton Altaparmakov, Erik Larsson, Jean-Pierre Andre, Szabolcs Szakacsits)
This commit is contained in:
parent
c7252ba416
commit
51f768af3b
@ -39,6 +39,9 @@ typedef struct _ntfs_attr_search_ctx ntfs_attr_search_ctx;
|
||||
extern ntfschar AT_UNNAMED[];
|
||||
extern ntfschar STREAM_SDS[];
|
||||
|
||||
/* The little endian Unicode string $TXF_DATA as a global constant. */
|
||||
extern ntfschar TXF_DATA[10];
|
||||
|
||||
/**
|
||||
* enum ntfs_lcn_special_values - special return values for ntfs_*_vcn_to_lcn()
|
||||
*
|
||||
@ -281,8 +284,6 @@ extern runlist_element *ntfs_attr_find_vcn(ntfs_attr *na, const VCN vcn);
|
||||
|
||||
extern int ntfs_attr_size_bounds_check(const ntfs_volume *vol,
|
||||
const ATTR_TYPES type, const s64 size);
|
||||
extern int ntfs_attr_can_be_non_resident(const ntfs_volume *vol,
|
||||
const ATTR_TYPES type);
|
||||
extern int ntfs_attr_can_be_resident(const ntfs_volume *vol,
|
||||
const ATTR_TYPES type);
|
||||
int ntfs_attr_make_non_resident(ntfs_attr *na,
|
||||
|
@ -1,11 +1,12 @@
|
||||
/**
|
||||
* attrib.c - Attribute handling code. Originated from the Linux-NTFS project.
|
||||
*
|
||||
* Copyright (c) 2000-2005 Anton Altaparmakov
|
||||
* Copyright (c) 2000-2010 Anton Altaparmakov
|
||||
* Copyright (c) 2002-2005 Richard Russon
|
||||
* Copyright (c) 2002-2008 Szabolcs Szakacsits
|
||||
* Copyright (c) 2004-2007 Yura Pakhuchiy
|
||||
* Copyright (c) 2007-2009 Jean-Pierre Andre
|
||||
* Copyright (c) 2007-2010 Jean-Pierre Andre
|
||||
* Copyright (c) 2010 Erik Larsson
|
||||
*
|
||||
* This program/include file is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as published
|
||||
@ -69,6 +70,17 @@ ntfschar STREAM_SDS[] = { const_cpu_to_le16('$'),
|
||||
const_cpu_to_le16('S'),
|
||||
const_cpu_to_le16('\0') };
|
||||
|
||||
ntfschar TXF_DATA[] = { const_cpu_to_le16('$'),
|
||||
const_cpu_to_le16('T'),
|
||||
const_cpu_to_le16('X'),
|
||||
const_cpu_to_le16('F'),
|
||||
const_cpu_to_le16('_'),
|
||||
const_cpu_to_le16('D'),
|
||||
const_cpu_to_le16('A'),
|
||||
const_cpu_to_le16('T'),
|
||||
const_cpu_to_le16('A'),
|
||||
const_cpu_to_le16('\0') };
|
||||
|
||||
static int NAttrFlag(ntfs_attr *na, FILE_ATTR_FLAGS flag)
|
||||
{
|
||||
if (na->type == AT_DATA && na->name == AT_UNNAMED)
|
||||
@ -3008,10 +3020,14 @@ int ntfs_attr_size_bounds_check(const ntfs_volume *vol, const ATTR_TYPES type,
|
||||
/**
|
||||
* ntfs_attr_can_be_non_resident - check if an attribute can be non-resident
|
||||
* @vol: ntfs volume to which the attribute belongs
|
||||
* @type: attribute type which to check
|
||||
* @type: attribute type to check
|
||||
* @name: attribute name to check
|
||||
* @name_len: attribute name length
|
||||
*
|
||||
* Check whether the attribute of @type on the ntfs volume @vol is allowed to
|
||||
* be non-resident. This information is obtained from $AttrDef system file.
|
||||
* Check whether the attribute of @type and @name with name length @name_len on
|
||||
* the ntfs volume @vol is allowed to be non-resident. This information is
|
||||
* obtained from $AttrDef system file and is augmented by rules imposed by
|
||||
* Microsoft (e.g. see http://support.microsoft.com/kb/974729/).
|
||||
*
|
||||
* Return 0 if the attribute is allowed to be non-resident and -1 if not or an
|
||||
* error occurred. On error the error code is stored in errno. The following
|
||||
@ -3020,16 +3036,34 @@ int ntfs_attr_size_bounds_check(const ntfs_volume *vol, const ATTR_TYPES type,
|
||||
* ENOENT - The attribute @type is not specified in $AttrDef.
|
||||
* EINVAL - Invalid parameters (e.g. @vol is not valid).
|
||||
*/
|
||||
int ntfs_attr_can_be_non_resident(const ntfs_volume *vol, const ATTR_TYPES type)
|
||||
static int ntfs_attr_can_be_non_resident(const ntfs_volume *vol, const ATTR_TYPES type,
|
||||
const ntfschar *name, int name_len)
|
||||
{
|
||||
ATTR_DEF *ad;
|
||||
BOOL allowed;
|
||||
|
||||
/* Find the attribute definition record in $AttrDef. */
|
||||
ad = ntfs_attr_find_in_attrdef(vol, type);
|
||||
if (!ad)
|
||||
return -1;
|
||||
/* Check the flags and return the result. */
|
||||
if (ad->flags & ATTR_DEF_RESIDENT) {
|
||||
/*
|
||||
* Microsoft has decreed that $LOGGED_UTILITY_STREAM attributes with a
|
||||
* name of $TXF_DATA must be resident despite the entry for
|
||||
* $LOGGED_UTILITY_STREAM in $AttrDef allowing them to be non-resident.
|
||||
* Failure to obey this on the root directory mft record of a volume
|
||||
* causes Windows Vista and later to see the volume as a RAW volume and
|
||||
* thus cannot mount it at all.
|
||||
*/
|
||||
if ((type == AT_LOGGED_UTILITY_STREAM)
|
||||
&& name
|
||||
&& ntfs_names_are_equal(TXF_DATA, 9, name, name_len,
|
||||
CASE_SENSITIVE, vol->upcase, vol->upcase_len))
|
||||
allowed = FALSE;
|
||||
else {
|
||||
/* Find the attribute definition record in $AttrDef. */
|
||||
ad = ntfs_attr_find_in_attrdef(vol, type);
|
||||
if (!ad)
|
||||
return -1;
|
||||
/* Check the flags and return the result. */
|
||||
allowed = !(ad->flags & ATTR_DEF_RESIDENT);
|
||||
}
|
||||
if (!allowed) {
|
||||
errno = EPERM;
|
||||
ntfs_log_trace("Attribute can't be non-resident\n");
|
||||
return -1;
|
||||
@ -3294,7 +3328,7 @@ int ntfs_non_resident_attr_record_add(ntfs_inode *ni, ATTR_TYPES type,
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ntfs_attr_can_be_non_resident(ni->vol, type)) {
|
||||
if (ntfs_attr_can_be_non_resident(ni->vol, type, name, name_len)) {
|
||||
if (errno == EPERM)
|
||||
ntfs_log_perror("Attribute can't be non resident");
|
||||
else
|
||||
@ -3589,7 +3623,7 @@ int ntfs_attr_add(ntfs_inode *ni, ATTR_TYPES type,
|
||||
}
|
||||
|
||||
/* Sanity checks for always resident attributes. */
|
||||
if (ntfs_attr_can_be_non_resident(ni->vol, type)) {
|
||||
if (ntfs_attr_can_be_non_resident(ni->vol, type, name, name_len)) {
|
||||
if (errno != EPERM) {
|
||||
err = errno;
|
||||
ntfs_log_perror("ntfs_attr_can_be_non_resident failed");
|
||||
@ -4154,7 +4188,7 @@ int ntfs_attr_make_non_resident(ntfs_attr *na,
|
||||
}
|
||||
|
||||
/* Check that the attribute is allowed to be non-resident. */
|
||||
if (ntfs_attr_can_be_non_resident(vol, na->type))
|
||||
if (ntfs_attr_can_be_non_resident(vol, na->type, na->name, na->name_len))
|
||||
return -1;
|
||||
|
||||
new_allocated_size = (le32_to_cpu(a->value_length) + vol->cluster_size
|
||||
|
Loading…
Reference in New Issue
Block a user