ntfscat now works with attribute names
ntfscat now removes fixup from: $MFT/$DATA $MFTMirr/$DATA anydir/$INDEX_ALLOCATIONedge.strict_endians
							parent
							
								
									09936e5c22
								
							
						
					
					
						commit
						0e364b49aa
					
				|  | @ -32,13 +32,48 @@ is equivalent to | |||
| .BR "\-f \-v" . | ||||
| Long named options can be abbreviated to any unique prefix of their name. | ||||
| .TP | ||||
| .B \-f | ||||
| .B "\-a " desc | ||||
| .br | ||||
| .ns | ||||
| .TP | ||||
| .B \-\-force | ||||
| This will override some sensible defaults, such as not working with a mounted | ||||
| volume.  Use this option with caution. | ||||
| .B "\-\-attribute " desc | ||||
| Display the contents of a particular attribute.  By default, the unname $DATA | ||||
| attribute will be shown.  The attribute can be specified by number (in decimal | ||||
| or hexadecimal), or by name. | ||||
| .TS | ||||
| lB lB lB | ||||
| l l l. | ||||
| Hex	Decimal	Name | ||||
| 0x10	16	"$STANDARD_INFORMATION", | ||||
| 0x20	32	"$ATTRIBUTE_LIST", | ||||
| 0x30	48	"$FILE_NAME", | ||||
| 0x40	64	"$OBJECT_ID", | ||||
| 0x50	80	"$SECURITY_DESCRIPTOR", | ||||
| 0x60	96	"$VOLUME_NAME", | ||||
| 0x70	112	"$VOLUME_INFORMATION", | ||||
| 0x80	128	"$DATA", | ||||
| 0x90	144	"$INDEX_ROOT", | ||||
| 0xA0	160	"$INDEX_ALLOCATION", | ||||
| 0xB0	176	"$BITMAP", | ||||
| 0xC0	192	"$REPARSE_POINT", | ||||
| 0xD0	208	"$EA_INFORMATION", | ||||
| 0xE0	224	"$EA", | ||||
| 0xF0	240	"$PROPERTY_SET", | ||||
| 0x100	256	"$LOGGED_UTILITY_STREAM", | ||||
| .TE | ||||
| .br | ||||
| .B Notes | ||||
| .br | ||||
| The attribute names may be given without the leading $ symbol. | ||||
| .br | ||||
| If you use the $ symbol, you must escape it from the shell. | ||||
| .TP | ||||
| .B "\-i " num | ||||
| .br | ||||
| .ns | ||||
| .TP | ||||
| .B "\-\-inode " num | ||||
| Specify a file by its inode number instead of its name. | ||||
| .TP | ||||
| .B \-h | ||||
| .br | ||||
|  | @ -66,7 +101,7 @@ Show the version number, copyright and license | |||
| .br | ||||
| .ns | ||||
| .TP | ||||
| .B \-\-vebose | ||||
| .B \-\-verbose | ||||
| Display more debug/warning/error messages. | ||||
| .SH EXAMPLES | ||||
| Display the contents of a file in the root of an NTFS volume. | ||||
|  | @ -79,6 +114,14 @@ Display the contents of a file in a subdirectory of an NTFS volume. | |||
| .RS | ||||
| .sp | ||||
| .B ntfscat /dev/hda1 /winnt/system32/drivers/etc/hosts | ||||
| .RE | ||||
| .sp | ||||
| Display the contents of the $INDEX_ROOT attribute of the root directory (inode | ||||
| 5). | ||||
| .RS | ||||
| .sp | ||||
| .B ntfscat /dev/hda1 \-a INDEX_ROOT \-i 5 | hexdump \-C | ||||
| .RE | ||||
| .SH BUGS | ||||
| .B ntfscat | ||||
| was written in a short time, to get something "out there".  It needs a lot more work. | ||||
|  |  | |||
|  | @ -1,8 +1,8 @@ | |||
| /**
 | ||||
|  * ntfscat - Part of the Linux-NTFS project. | ||||
|  * | ||||
|  * Copyright (c) 2003 Richard Russon | ||||
|  * Copyright (c) 2003 Anton Altaparmakov | ||||
|  * Copyright (c) 2003-2005 Richard Russon | ||||
|  * Copyright (c) 2003      Anton Altaparmakov | ||||
|  * | ||||
|  * This utility will concatenate files and print on the standard output. | ||||
|  * | ||||
|  | @ -70,7 +70,7 @@ static void version (void) | |||
| static void usage (void) | ||||
| { | ||||
| 	Printf ("\nUsage: %s [options] device [file]\n\n" | ||||
| 		"    -a, --attribute num   Display this attribute\n" | ||||
| 		"    -a, --attribute desc  Display this attribute (name or number)\n" | ||||
| 		"    -i, --inode num       Display this inode\n\n" | ||||
| 		"    -f  --force           Use less caution\n" | ||||
| 		"    -h  --help            Print this help\n" | ||||
|  | @ -84,6 +84,60 @@ static void usage (void) | |||
| 	Printf ("%s%s\n", ntfs_bugs, ntfs_home); | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * parse_attribute - Read an attribute name, or number | ||||
|  * @value:   String to be parsed | ||||
|  * @attr:    Resulting attribute id (on success) | ||||
|  * | ||||
|  * Read a string representing an attribute.  It may be a decimal, octal or | ||||
|  * hexadecimal number, or the attribute name in full.  The leading $ sign is | ||||
|  * optional. | ||||
|  * | ||||
|  * Return:  1  Success, a valid attribute name or number | ||||
|  *	    0  Error, not an attribute name or number | ||||
|  */ | ||||
| static int parse_attribute (const char *value, ATTR_TYPES *attr) | ||||
| { | ||||
| 	static const char *attr_name[] = { | ||||
| 		"$STANDARD_INFORMATION", | ||||
| 		"$ATTRIBUTE_LIST", | ||||
| 		"$FILE_NAME", | ||||
| 		"$OBJECT_ID", | ||||
| 		"$SECURITY_DESCRIPTOR", | ||||
| 		"$VOLUME_NAME", | ||||
| 		"$VOLUME_INFORMATION", | ||||
| 		"$DATA", | ||||
| 		"$INDEX_ROOT", | ||||
| 		"$INDEX_ALLOCATION", | ||||
| 		"$BITMAP", | ||||
| 		"$REPARSE_POINT", | ||||
| 		"$EA_INFORMATION", | ||||
| 		"$EA", | ||||
| 		"$PROPERTY_SET", | ||||
| 		"$LOGGED_UTILITY_STREAM", | ||||
| 		NULL | ||||
| 	}; | ||||
| 
 | ||||
| 	int i; | ||||
| 	long num; | ||||
| 
 | ||||
| 	for (i = 0; attr_name[i]; i++) { | ||||
| 		if ((strcmp (value, attr_name[i]) == 0) || | ||||
| 		    (strcmp (value, attr_name[i]+1) == 0)) { | ||||
| 			*attr = (ATTR_TYPES) ((i+1)*16); | ||||
| 			return 1; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	num = strtol (value, NULL, 0); | ||||
| 	if ((num > 0) && (num < 257)) { | ||||
| 		*attr = (ATTR_TYPES) num; | ||||
| 		return 1; | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * parse_options - Read and validate the programs command line | ||||
|  * | ||||
|  | @ -113,7 +167,7 @@ static int parse_options (int argc, char **argv) | |||
| 	int err  = 0; | ||||
| 	int ver  = 0; | ||||
| 	int help = 0; | ||||
| 	s64 attr; | ||||
| 	ATTR_TYPES attr = AT_UNUSED; | ||||
| 
 | ||||
| 	opterr = 0; /* We'll handle the errors, thank you. */ | ||||
| 
 | ||||
|  | @ -133,16 +187,16 @@ static int parse_options (int argc, char **argv) | |||
| 			} | ||||
| 			break; | ||||
| 		case 'a': | ||||
| 			if (opts.attr != (ATTR_TYPES)-1) | ||||
| 			if (opts.attr != (ATTR_TYPES)-1) { | ||||
| 				Eprintf("You must specify exactly one attribute.\n"); | ||||
| 			else if (utils_parse_size(optarg, &attr, FALSE)) { | ||||
| 				opts.attr = (ATTR_TYPES)attr; | ||||
| 			} else if (parse_attribute (optarg, &attr) > 0) { | ||||
| 				opts.attr = attr; | ||||
| 				break; | ||||
| 			} else | ||||
| 				Eprintf("Couldn't parse attribute number.\n"); | ||||
| 			} else { | ||||
| 				Eprintf("Couldn't parse attribute.\n"); | ||||
| 			} | ||||
| 			err++; | ||||
| 			break; | ||||
| 
 | ||||
| 		case 'f': | ||||
| 			opts.force++; | ||||
| 			break; | ||||
|  | @ -207,19 +261,42 @@ static int parse_options (int argc, char **argv) | |||
| 	return (!err && !help && !ver); | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * index_get_size - Find the INDX block size from the index root | ||||
|  * @inode:  Inode of the directory to be checked | ||||
|  * | ||||
|  * Find the size of a directory's INDX block from the INDEX_ROOT attribute. | ||||
|  * | ||||
|  * Return:  n  Success, the INDX blocks are n bytes in size | ||||
|  *	    0  Error, not a directory | ||||
|  */ | ||||
| static int index_get_size (ntfs_inode *inode) | ||||
| { | ||||
| 	ATTR_RECORD *attr90; | ||||
| 	INDEX_ROOT *iroot; | ||||
| 
 | ||||
| 	attr90 = find_first_attribute (AT_INDEX_ROOT, inode->mrec); | ||||
| 	if (!attr90) | ||||
| 		return 0;	// not a directory
 | ||||
| 
 | ||||
| 	iroot = (INDEX_ROOT*)((u8*)attr90 + le16_to_cpu(attr90->value_offset)); | ||||
| 
 | ||||
| 	return iroot->index_block_size; | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * cat | ||||
|  */ | ||||
| static int cat (ntfs_volume *vol __attribute__((unused)), ntfs_inode *inode, | ||||
| 		ATTR_TYPES type, ntfschar *name __attribute__((unused)), | ||||
| static int cat (ntfs_volume *vol, ntfs_inode *inode, ATTR_TYPES type, | ||||
| 		ntfschar *name __attribute__((unused)), | ||||
| 		int namelen __attribute__((unused))) | ||||
| { | ||||
| 	/* increase 1024 only if you fix partial writes below */ | ||||
| 	const int bufsize = 1024; | ||||
| 	const int bufsize = 4096; | ||||
| 	char *buffer; | ||||
| 	ntfs_attr *attr; | ||||
| 	s64 bytes_read, written; | ||||
| 	s64 offset; | ||||
| 	u32 block_size; | ||||
| 
 | ||||
| 	buffer = malloc (bufsize); | ||||
| 	if (!buffer) | ||||
|  | @ -227,14 +304,28 @@ static int cat (ntfs_volume *vol __attribute__((unused)), ntfs_inode *inode, | |||
| 
 | ||||
| 	attr = ntfs_attr_open (inode, type, NULL, 0); | ||||
| 	if (!attr) { | ||||
| 		Eprintf ("Cannot cat a directory.\n"); | ||||
| 		Eprintf ("Cannot find attribute type 0x%lx.\n", (long) type); | ||||
| 		free (buffer); | ||||
| 		return 1; | ||||
| 	} | ||||
| 
 | ||||
| 	if ((inode->mft_no < 2) && (attr->type == AT_DATA)) | ||||
| 		block_size = vol->mft_record_size; | ||||
| 	else if (attr->type == AT_INDEX_ALLOCATION) | ||||
| 		block_size = index_get_size (inode); | ||||
| 	else | ||||
| 		block_size = 0; | ||||
| 
 | ||||
| 	offset = 0; | ||||
| 	for (;;) { | ||||
| 		bytes_read = ntfs_attr_pread (attr, offset, bufsize, buffer); | ||||
| 		if (block_size > 0) { | ||||
| 			// These types have fixup
 | ||||
| 			bytes_read = ntfs_attr_mst_pread(attr, offset, 1, block_size, buffer); | ||||
| 			bytes_read *= block_size; | ||||
| 		} else { | ||||
| 			bytes_read = ntfs_attr_pread (attr, offset, bufsize, buffer); | ||||
| 		} | ||||
| 		//fprintf (stderr, "read %lld bytes\n", bytes_read);
 | ||||
| 		if (bytes_read == -1) { | ||||
| 			perror ("ERROR: Couldn't read file"); | ||||
| 			break; | ||||
|  | @ -275,8 +366,6 @@ int main (int argc, char *argv[]) | |||
| 
 | ||||
| 	utils_set_locale(); | ||||
| 
 | ||||
| 	//XXX quieten errors, temporarily
 | ||||
| 
 | ||||
| 	vol = utils_mount_volume (opts.device, MS_RDONLY, opts.force); | ||||
| 	if (!vol) { | ||||
| 		perror("ERROR: couldn't mount volume"); | ||||
|  | @ -301,12 +390,8 @@ int main (int argc, char *argv[]) | |||
| 
 | ||||
| 	ntfs_inode_close (inode); | ||||
| 	ntfs_umount (vol, FALSE); | ||||
| #if 0 | ||||
| 	if (result) | ||||
| 		Printf ("failed\n"); | ||||
| 	else | ||||
| 		Printf ("success\n"); | ||||
| #endif | ||||
| 
 | ||||
| 	return result; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue