diff --git a/ChangeLog b/ChangeLog index 8adb452d..d74a275b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -10,6 +10,7 @@ xx/xx/xxxx - 1.10.1-WIP rely on libntfs. (Yura) - ntfsresize: support bad clusters list ($BadClus:$Bad), a.k.a. disks having bad sectors if the new --bad-sectors option is used. (Szaka) + - ntfsinfo: Dump $EA_INFORMATION and $EA attributes. (Yura) 20/06/2005 - 1.10.0 - Lots of new features, enhancements, and bug fixes. diff --git a/include/ntfs/layout.h b/include/ntfs/layout.h index 027a04d6..71d9c515 100644 --- a/include/ntfs/layout.h +++ b/include/ntfs/layout.h @@ -2,6 +2,7 @@ * layout.h - Ntfs on-disk layout structures. Part of the Linux-NTFS project. * * Copyright (c) 2000-2004 Anton Altaparmakov + * Copyright (c) 2005 Yura Pakhuchiy * * 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 @@ -2294,7 +2295,7 @@ typedef struct { /* * Attribute: Extended attribute (EA) information (0xd0). * - * NOTE: Always resident. (Is this true???) + * NOTE: Always resident. */ typedef struct { u16 ea_length; /* Byte size of the packed extended @@ -2318,21 +2319,20 @@ typedef enum { /* * Attribute: Extended attribute (EA) (0xe0). * - * NOTE: Always non-resident. (Is this true?) - * * Like the attribute list and the index buffer list, the EA attribute value is * a sequence of EA_ATTR variable length records. * * FIXME: It appears weird that the EA name is not Unicode. Is it true? + * FIXME: It seems that name is always uppercased. Is it true? */ typedef struct { u32 next_entry_offset; /* Offset to the next EA_ATTR. */ EA_FLAGS flags; /* Flags describing the EA. */ - u8 ea_name_length; /* Length of the name of the extended + u8 name_length; /* Length of the name of the extended attribute in bytes. */ - u16 ea_value_length; /* Byte size of the EA's value. */ - u8 ea_name[0]; /* Name of the EA. */ - u8 ea_value[0]; /* The value of the EA. Immediately + u16 value_length; /* Byte size of the EA's value. */ + u8 name[0]; /* Name of the EA. */ + u8 value[0]; /* The value of the EA. Immediately follows the name. */ } __attribute__ ((__packed__)) EA_ATTR; diff --git a/ntfsprogs/ntfsinfo.c b/ntfsprogs/ntfsinfo.c index dc5fb946..cda2754b 100644 --- a/ntfsprogs/ntfsinfo.c +++ b/ntfsprogs/ntfsinfo.c @@ -40,8 +40,6 @@ * * Still need to do: * $REPARSE_POINT/$SYMBOLIC_LINK - * $EA_INFORMATION - * $EA * $PROPERTY_SET * $LOGGED_UTILITY_STREAM */ @@ -844,21 +842,28 @@ static void ntfs_dump_attr_security_descriptor(ATTR_RECORD *attr, ntfs_volume *v printf("\tAttribute instance:\t %u\n", le16_to_cpu(attr->instance)); if (attr->non_resident) { + /* FIXME: We don't handle fragmented mapping pairs case. */ runlist *rl = ntfs_mapping_pairs_decompress(vol, attr, 0); if (rl) { s64 data_size, bytes_read; data_size = sle64_to_cpu(attr->data_size); sec_desc_attr = malloc(data_size); + if (!sec_desc_attr) { + perror("malloc failed"); + free(rl); + return; + } bytes_read = ntfs_rl_pread(vol, rl, 0, data_size, sec_desc_attr); if (bytes_read != data_size) { Eprintf("ntfsinfo error: could not " "read security descriptor\n"); + free(rl); free(sec_desc_attr); return; } - free (rl); + free(rl); } else { Eprintf("ntfsinfo error: could not " "decompress runlist\n"); @@ -1462,10 +1467,18 @@ static void ntfs_dump_attr_reparse_point(ATTR_RECORD *attr __attribute__((unused * * dump the ea_information attribute */ -static void ntfs_dump_attr_ea_information(ATTR_RECORD *attr __attribute__((unused))) +static void ntfs_dump_attr_ea_information(ATTR_RECORD *attr) { + EA_INFORMATION *ea_info; + + ea_info = (EA_INFORMATION*)((u8*)attr + + le16_to_cpu(attr->value_offset)); printf("Dumping attribute $EA_INFORMATION (0xD0)\n"); - printf("\tTODO\n"); + printf("\tPacked EA length:\t %u\n", le16_to_cpu(ea_info->ea_length)); + printf("\tNEED_EA count:\t\t %u\n", + le16_to_cpu(ea_info->need_ea_count)); + printf("\tUnpacked EA length:\t %u\n", + le32_to_cpu(ea_info->ea_query_length)); } /** @@ -1473,10 +1486,71 @@ static void ntfs_dump_attr_ea_information(ATTR_RECORD *attr __attribute__((unuse * * dump the ea attribute */ -static void ntfs_dump_attr_ea(ATTR_RECORD *attr __attribute__((unused))) +static void ntfs_dump_attr_ea(ATTR_RECORD *attr, ntfs_volume *vol) { + EA_ATTR *ea; + u8 *buf = NULL; + printf("Dumping attribute $EA (0xE0)\n"); - printf("\tTODO\n"); + if (attr->non_resident) { + runlist *rl; + s64 data_size; + + data_size = sle64_to_cpu(attr->data_size); + printf("\tIs resident? \t\t No\n"); + printf("\tData size:\t\t %lld\n", data_size); + /* FIXME: We don't handle fragmented mapping pairs case. */ + rl = ntfs_mapping_pairs_decompress(vol, attr, 0); + if (rl) { + s64 bytes_read; + + buf = malloc(data_size); + if (!buf) { + perror("malloc failed"); + free(rl); + return; + } + bytes_read = ntfs_rl_pread(vol, rl, 0, data_size, buf); + if (bytes_read != data_size) { + perror("ntfs_rl_pread failed"); + free(buf); + free(rl); + return; + } + free(rl); + ea = (EA_ATTR*)buf; + } else { + perror("ntfs_mapping_pairs_decompress failed"); + return; + } + } else { + printf("\tIs resident? \t\t Yes\n"); + printf("\tAttribute value length:\t %u\n", + le32_to_cpu(attr->value_length)); + ea = (EA_ATTR*)((u8*)attr + le16_to_cpu(attr->value_offset)); + } + while (ea) { + printf("\n\tFlags:\t\t "); + if (ea->flags) { + if (ea->flags == NEED_EA) + printf("NEED_EA\n"); + else + printf("Unknown (0x%02x)\n", ea->flags); + } else + printf("\n"); + printf("\tName length:\t %d\n", ea->name_length); + printf("\tValue length:\t %d\n", + le16_to_cpu(ea->value_length)); + printf("\tName:\t\t '%s'\n", ea->name); + printf("\tValue:\t\t '%s'\n", ea->value + ea->name_length + 1); + if (ea->next_entry_offset) + ea = (EA_ATTR*)((u8*)ea + + le32_to_cpu(ea->next_entry_offset)); + else + ea = NULL; + } + if (buf) + free(buf); } /** @@ -1714,7 +1788,7 @@ static void ntfs_dump_file_attributes(ntfs_inode *inode) ntfs_dump_attr_ea_information(ctx->attr); break; case AT_EA: - ntfs_dump_attr_ea(ctx->attr); + ntfs_dump_attr_ea(ctx->attr, inode->vol); break; case AT_PROPERTY_SET: ntfs_dump_attr_property_set(ctx->attr);