diff --git a/include/ntfs-3g/attrib.h b/include/ntfs-3g/attrib.h index aa40637c..bcdb0117 100644 --- a/include/ntfs-3g/attrib.h +++ b/include/ntfs-3g/attrib.h @@ -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() * diff --git a/libntfs-3g/attrib.c b/libntfs-3g/attrib.c index e876af67..d7316e06 100644 --- a/libntfs-3g/attrib.c +++ b/libntfs-3g/attrib.c @@ -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 @@ -82,7 +83,8 @@ ntfschar TXF_DATA[] = { 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('A'), + const_cpu_to_le16('\0') }; static int NAttrFlag(ntfs_attr *na, FILE_ATTR_FLAGS flag) { @@ -3012,10 +3014,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 @@ -3025,19 +3031,23 @@ int ntfs_attr_size_bounds_check(const ntfs_volume *vol, const ATTR_TYPES type, * EINVAL - Invalid parameters (e.g. @vol is not valid). */ static int ntfs_attr_can_be_non_resident(const ntfs_volume *vol, const ATTR_TYPES type, - const ntfschar *name, int namelen) + const ntfschar *name, int name_len) { ATTR_DEF *ad; BOOL allowed; - /* - * hard-coded rule for $TXF_DATA - * see http://support.microsoft.com/kb/974729 - */ + /* + * 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) - && (namelen == 9) && name - && !memcmp(name,TXF_DATA,18)) + && 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. */ @@ -4162,7 +4172,6 @@ int ntfs_attr_make_non_resident(ntfs_attr *na, ntfs_volume *vol = na->ni->vol; ATTR_REC *a = ctx->attr; runlist *rl; - const ntfschar *name; int mp_size, mp_ofs, name_ofs, arec_size, err; ntfs_log_trace("Entering for inode 0x%llx, attr 0x%x.\n", (unsigned long @@ -4177,8 +4186,7 @@ int ntfs_attr_make_non_resident(ntfs_attr *na, } /* Check that the attribute is allowed to be non-resident. */ - name = (const ntfschar*)((const char*)a + le16_to_cpu(a->name_offset)); - if (ntfs_attr_can_be_non_resident(vol, na->type, name, a->name_length)) + 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 diff --git a/libntfs-3g/volume.c b/libntfs-3g/volume.c index b09708ea..863bf8cc 100644 --- a/libntfs-3g/volume.c +++ b/libntfs-3g/volume.c @@ -4,6 +4,7 @@ * Copyright (c) 2000-2006 Anton Altaparmakov * Copyright (c) 2002-2009 Szabolcs Szakacsits * Copyright (c) 2004-2005 Richard Russon + * Copyright (c) 2010 Jean-Pierre Andre * * 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 @@ -68,8 +69,6 @@ #include "cache.h" #include "misc.h" -extern ntfschar TXF_DATA[]; - const char *ntfs_home = "Ntfs-3g news, support and information: http://ntfs-3g.org\n"; @@ -813,7 +812,6 @@ static int fix_txf_data(ntfs_volume *vol) free(txf_data); } } - /* Done with the $AttrDef mft record. */ ntfs_attr_close(na); } if (ntfs_inode_close(ni)) {