1987da915Sopenharmony_ci/**
2987da915Sopenharmony_ci * ntfsinfo - Part of the Linux-NTFS project.
3987da915Sopenharmony_ci *
4987da915Sopenharmony_ci * Copyright (c) 2002-2004 Matthew J. Fanto
5987da915Sopenharmony_ci * Copyright (c) 2002-2006 Anton Altaparmakov
6987da915Sopenharmony_ci * Copyright (c) 2002-2005 Richard Russon
7987da915Sopenharmony_ci * Copyright (c) 2003-2006 Szabolcs Szakacsits
8987da915Sopenharmony_ci * Copyright (c) 2004-2005 Yuval Fledel
9987da915Sopenharmony_ci * Copyright (c) 2004-2007 Yura Pakhuchiy
10987da915Sopenharmony_ci * Copyright (c)      2005 Cristian Klein
11987da915Sopenharmony_ci * Copyright (c) 2011-2020 Jean-Pierre Andre
12987da915Sopenharmony_ci *
13987da915Sopenharmony_ci * This utility will dump a file's attributes.
14987da915Sopenharmony_ci *
15987da915Sopenharmony_ci * This program is free software; you can redistribute it and/or modify
16987da915Sopenharmony_ci * it under the terms of the GNU General Public License as published by
17987da915Sopenharmony_ci * the Free Software Foundation; either version 2 of the License, or
18987da915Sopenharmony_ci * (at your option) any later version.
19987da915Sopenharmony_ci *
20987da915Sopenharmony_ci * This program is distributed in the hope that it will be useful,
21987da915Sopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of
22987da915Sopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23987da915Sopenharmony_ci * GNU General Public License for more details.
24987da915Sopenharmony_ci *
25987da915Sopenharmony_ci * You should have received a copy of the GNU General Public License
26987da915Sopenharmony_ci * along with this program (in the main directory of the Linux-NTFS
27987da915Sopenharmony_ci * distribution in the file COPYING); if not, write to the Free Software
28987da915Sopenharmony_ci * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
29987da915Sopenharmony_ci */
30987da915Sopenharmony_ci/*
31987da915Sopenharmony_ci * TODO LIST:
32987da915Sopenharmony_ci *	- Better error checking. (focus on ntfs_dump_volume)
33987da915Sopenharmony_ci *	- Comment things better.
34987da915Sopenharmony_ci *	- More things at verbose mode.
35987da915Sopenharmony_ci *	- Dump ACLs when security_id exists (NTFS 3+ only).
36987da915Sopenharmony_ci *	- Clean ups.
37987da915Sopenharmony_ci *	- Internationalization.
38987da915Sopenharmony_ci *	- Add more Indexed Attr Types.
39987da915Sopenharmony_ci *	- Make formatting look more like www.flatcap.org/ntfs/info
40987da915Sopenharmony_ci *
41987da915Sopenharmony_ci *	Still not dumping certain attributes. Need to find the best
42987da915Sopenharmony_ci *	way to output some of these attributes.
43987da915Sopenharmony_ci *
44987da915Sopenharmony_ci *	Still need to do:
45987da915Sopenharmony_ci *	    $REPARSE_POINT/$SYMBOLIC_LINK
46987da915Sopenharmony_ci *	    $LOGGED_UTILITY_STREAM
47987da915Sopenharmony_ci */
48987da915Sopenharmony_ci
49987da915Sopenharmony_ci#include "config.h"
50987da915Sopenharmony_ci
51987da915Sopenharmony_ci#ifdef HAVE_STDIO_H
52987da915Sopenharmony_ci#include <stdio.h>
53987da915Sopenharmony_ci#endif
54987da915Sopenharmony_ci#ifdef HAVE_STDLIB_H
55987da915Sopenharmony_ci#include <stdlib.h>
56987da915Sopenharmony_ci#endif
57987da915Sopenharmony_ci#ifdef HAVE_STRING_H
58987da915Sopenharmony_ci#include <string.h>
59987da915Sopenharmony_ci#endif
60987da915Sopenharmony_ci#ifdef HAVE_TIME_H
61987da915Sopenharmony_ci#include <time.h>
62987da915Sopenharmony_ci#endif
63987da915Sopenharmony_ci#ifdef HAVE_GETOPT_H
64987da915Sopenharmony_ci#include <getopt.h>
65987da915Sopenharmony_ci#endif
66987da915Sopenharmony_ci#ifdef HAVE_ERRNO_H
67987da915Sopenharmony_ci#include <errno.h>
68987da915Sopenharmony_ci#endif
69987da915Sopenharmony_ci
70987da915Sopenharmony_ci#include "types.h"
71987da915Sopenharmony_ci#include "mft.h"
72987da915Sopenharmony_ci#include "attrib.h"
73987da915Sopenharmony_ci#include "layout.h"
74987da915Sopenharmony_ci#include "inode.h"
75987da915Sopenharmony_ci#include "index.h"
76987da915Sopenharmony_ci#include "utils.h"
77987da915Sopenharmony_ci#include "security.h"
78987da915Sopenharmony_ci#include "mst.h"
79987da915Sopenharmony_ci#include "dir.h"
80987da915Sopenharmony_ci#include "ntfstime.h"
81987da915Sopenharmony_ci/* #include "version.h" */
82987da915Sopenharmony_ci#include "support.h"
83987da915Sopenharmony_ci#include "misc.h"
84987da915Sopenharmony_ci
85987da915Sopenharmony_cistatic const char *EXEC_NAME = "ntfsinfo";
86987da915Sopenharmony_ci
87987da915Sopenharmony_cistatic struct options {
88987da915Sopenharmony_ci	const char *device;	/* Device/File to work with */
89987da915Sopenharmony_ci	const char *filename;	/* Resolve this filename to mft number */
90987da915Sopenharmony_ci	s64	 inode;		/* Info for this inode */
91987da915Sopenharmony_ci	int	 quiet;		/* Less output */
92987da915Sopenharmony_ci	int	 verbose;	/* Extra output */
93987da915Sopenharmony_ci	int	 force;		/* Override common sense */
94987da915Sopenharmony_ci	int	 notime;	/* Don't report timestamps at all */
95987da915Sopenharmony_ci	int	 mft;		/* Dump information about the volume as well */
96987da915Sopenharmony_ci} opts;
97987da915Sopenharmony_ci
98987da915Sopenharmony_cistruct RUNCOUNT {
99987da915Sopenharmony_ci	unsigned long runs;
100987da915Sopenharmony_ci	unsigned long fragments;
101987da915Sopenharmony_ci} ;
102987da915Sopenharmony_ci
103987da915Sopenharmony_ci/**
104987da915Sopenharmony_ci * version - Print version information about the program
105987da915Sopenharmony_ci *
106987da915Sopenharmony_ci * Print a copyright statement and a brief description of the program.
107987da915Sopenharmony_ci *
108987da915Sopenharmony_ci * Return:  none
109987da915Sopenharmony_ci */
110987da915Sopenharmony_cistatic void version(void)
111987da915Sopenharmony_ci{
112987da915Sopenharmony_ci	printf("\n%s v%s (libntfs-3g) - Display information about an NTFS "
113987da915Sopenharmony_ci			"Volume.\n\n", EXEC_NAME, VERSION);
114987da915Sopenharmony_ci	printf("Copyright (c)\n");
115987da915Sopenharmony_ci	printf("    2002-2004 Matthew J. Fanto\n");
116987da915Sopenharmony_ci	printf("    2002-2006 Anton Altaparmakov\n");
117987da915Sopenharmony_ci	printf("    2002-2005 Richard Russon\n");
118987da915Sopenharmony_ci	printf("    2003-2006 Szabolcs Szakacsits\n");
119987da915Sopenharmony_ci	printf("    2003      Leonard Norrgård\n");
120987da915Sopenharmony_ci	printf("    2004-2005 Yuval Fledel\n");
121987da915Sopenharmony_ci	printf("    2004-2007 Yura Pakhuchiy\n");
122987da915Sopenharmony_ci	printf("    2011-2018 Jean-Pierre Andre\n");
123987da915Sopenharmony_ci	printf("\n%s\n%s%s\n", ntfs_gpl, ntfs_bugs, ntfs_home);
124987da915Sopenharmony_ci}
125987da915Sopenharmony_ci
126987da915Sopenharmony_ci/**
127987da915Sopenharmony_ci * usage - Print a list of the parameters to the program
128987da915Sopenharmony_ci *
129987da915Sopenharmony_ci * Print a list of the parameters and options for the program.
130987da915Sopenharmony_ci *
131987da915Sopenharmony_ci * Return:  none
132987da915Sopenharmony_ci */
133987da915Sopenharmony_cistatic void usage(void)
134987da915Sopenharmony_ci{
135987da915Sopenharmony_ci	printf("\nUsage: %s [options] device\n"
136987da915Sopenharmony_ci		"    -i, --inode NUM  Display information about this inode\n"
137987da915Sopenharmony_ci		"    -F, --file FILE  Display information about this file (absolute path)\n"
138987da915Sopenharmony_ci		"    -m, --mft        Dump information about the volume\n"
139987da915Sopenharmony_ci		"    -t, --notime     Don't report timestamps\n"
140987da915Sopenharmony_ci		"\n"
141987da915Sopenharmony_ci		"    -f, --force      Use less caution\n"
142987da915Sopenharmony_ci		"    -q, --quiet      Less output\n"
143987da915Sopenharmony_ci		"    -v, --verbose    More output\n"
144987da915Sopenharmony_ci		"    -V, --version    Display version information\n"
145987da915Sopenharmony_ci		"    -h, --help       Display this help\n"
146987da915Sopenharmony_ci	        "\n",
147987da915Sopenharmony_ci		EXEC_NAME);
148987da915Sopenharmony_ci	printf("%s%s\n", ntfs_bugs, ntfs_home);
149987da915Sopenharmony_ci}
150987da915Sopenharmony_ci
151987da915Sopenharmony_ci/**
152987da915Sopenharmony_ci * parse_options - Read and validate the programs command line
153987da915Sopenharmony_ci *
154987da915Sopenharmony_ci * Read the command line, verify the syntax and parse the options.
155987da915Sopenharmony_ci * This function is very long, but quite simple.
156987da915Sopenharmony_ci *
157987da915Sopenharmony_ci * Return:  1 Success
158987da915Sopenharmony_ci *	    0 Error, one or more problems
159987da915Sopenharmony_ci */
160987da915Sopenharmony_cistatic int parse_options(int argc, char *argv[])
161987da915Sopenharmony_ci{
162987da915Sopenharmony_ci	static const char *sopt = "-:dfhi:F:mqtTvV";
163987da915Sopenharmony_ci	static const struct option lopt[] = {
164987da915Sopenharmony_ci		{ "force",	 no_argument,		NULL, 'f' },
165987da915Sopenharmony_ci		{ "help",	 no_argument,		NULL, 'h' },
166987da915Sopenharmony_ci		{ "inode",	 required_argument,	NULL, 'i' },
167987da915Sopenharmony_ci		{ "file",	 required_argument,	NULL, 'F' },
168987da915Sopenharmony_ci		{ "quiet",	 no_argument,		NULL, 'q' },
169987da915Sopenharmony_ci		{ "verbose",	 no_argument,		NULL, 'v' },
170987da915Sopenharmony_ci		{ "version",	 no_argument,		NULL, 'V' },
171987da915Sopenharmony_ci		{ "notime",	 no_argument,		NULL, 'T' },
172987da915Sopenharmony_ci		{ "mft",	 no_argument,		NULL, 'm' },
173987da915Sopenharmony_ci		{ NULL,		 0,			NULL,  0  }
174987da915Sopenharmony_ci	};
175987da915Sopenharmony_ci
176987da915Sopenharmony_ci	int c = -1;
177987da915Sopenharmony_ci	int err  = 0;
178987da915Sopenharmony_ci	int ver  = 0;
179987da915Sopenharmony_ci	int help = 0;
180987da915Sopenharmony_ci	int levels = 0;
181987da915Sopenharmony_ci
182987da915Sopenharmony_ci	opterr = 0; /* We'll handle the errors, thank you. */
183987da915Sopenharmony_ci
184987da915Sopenharmony_ci	opts.inode = -1;
185987da915Sopenharmony_ci	opts.filename = NULL;
186987da915Sopenharmony_ci
187987da915Sopenharmony_ci	while ((c = getopt_long(argc, argv, sopt, lopt, NULL)) != -1) {
188987da915Sopenharmony_ci		switch (c) {
189987da915Sopenharmony_ci		case 1:
190987da915Sopenharmony_ci			if (!opts.device)
191987da915Sopenharmony_ci				opts.device = optarg;
192987da915Sopenharmony_ci			else
193987da915Sopenharmony_ci				err++;
194987da915Sopenharmony_ci			break;
195987da915Sopenharmony_ci		case 'i':
196987da915Sopenharmony_ci			if ((opts.inode != -1) ||
197987da915Sopenharmony_ci			    (!utils_parse_size(optarg, &opts.inode, FALSE))) {
198987da915Sopenharmony_ci				err++;
199987da915Sopenharmony_ci			}
200987da915Sopenharmony_ci			break;
201987da915Sopenharmony_ci		case 'F':
202987da915Sopenharmony_ci			if (opts.filename == NULL) {
203987da915Sopenharmony_ci				/* The inode can not be resolved here,
204987da915Sopenharmony_ci				   store the filename */
205987da915Sopenharmony_ci				opts.filename = argv[optind-1];
206987da915Sopenharmony_ci			} else {
207987da915Sopenharmony_ci				/* "-F" can't appear more than once */
208987da915Sopenharmony_ci				err++;
209987da915Sopenharmony_ci			}
210987da915Sopenharmony_ci			break;
211987da915Sopenharmony_ci		case 'f':
212987da915Sopenharmony_ci			opts.force++;
213987da915Sopenharmony_ci			break;
214987da915Sopenharmony_ci		case 'h':
215987da915Sopenharmony_ci			help++;
216987da915Sopenharmony_ci			break;
217987da915Sopenharmony_ci		case 'q':
218987da915Sopenharmony_ci			opts.quiet++;
219987da915Sopenharmony_ci			ntfs_log_clear_levels(NTFS_LOG_LEVEL_QUIET);
220987da915Sopenharmony_ci			break;
221987da915Sopenharmony_ci		case 't':
222987da915Sopenharmony_ci			opts.notime++;
223987da915Sopenharmony_ci			break;
224987da915Sopenharmony_ci		case 'T':
225987da915Sopenharmony_ci			/* 'T' is deprecated, notify */
226987da915Sopenharmony_ci			ntfs_log_error("Option 'T' is deprecated, it was "
227987da915Sopenharmony_ci				"replaced by 't'.\n");
228987da915Sopenharmony_ci			err++;
229987da915Sopenharmony_ci			break;
230987da915Sopenharmony_ci		case 'v':
231987da915Sopenharmony_ci			opts.verbose++;
232987da915Sopenharmony_ci			ntfs_log_set_levels(NTFS_LOG_LEVEL_VERBOSE);
233987da915Sopenharmony_ci			break;
234987da915Sopenharmony_ci		case 'V':
235987da915Sopenharmony_ci			ver++;
236987da915Sopenharmony_ci			break;
237987da915Sopenharmony_ci		case 'm':
238987da915Sopenharmony_ci			opts.mft++;
239987da915Sopenharmony_ci			break;
240987da915Sopenharmony_ci		case '?':
241987da915Sopenharmony_ci			if (optopt=='?') {
242987da915Sopenharmony_ci				help++;
243987da915Sopenharmony_ci				continue;
244987da915Sopenharmony_ci			}
245987da915Sopenharmony_ci			if (ntfs_log_parse_option(argv[optind-1]))
246987da915Sopenharmony_ci				continue;
247987da915Sopenharmony_ci			ntfs_log_error("Unknown option '%s'.\n",
248987da915Sopenharmony_ci					argv[optind-1]);
249987da915Sopenharmony_ci			err++;
250987da915Sopenharmony_ci			break;
251987da915Sopenharmony_ci		case ':':
252987da915Sopenharmony_ci			ntfs_log_error("Option '%s' requires an "
253987da915Sopenharmony_ci					"argument.\n", argv[optind-1]);
254987da915Sopenharmony_ci			err++;
255987da915Sopenharmony_ci			break;
256987da915Sopenharmony_ci		default:
257987da915Sopenharmony_ci			ntfs_log_error("Unhandled option case: %d.\n", c);
258987da915Sopenharmony_ci			err++;
259987da915Sopenharmony_ci			break;
260987da915Sopenharmony_ci		}
261987da915Sopenharmony_ci	}
262987da915Sopenharmony_ci
263987da915Sopenharmony_ci	/* Make sure we're in sync with the log levels */
264987da915Sopenharmony_ci	levels = ntfs_log_get_levels();
265987da915Sopenharmony_ci	if (levels & NTFS_LOG_LEVEL_VERBOSE)
266987da915Sopenharmony_ci		opts.verbose++;
267987da915Sopenharmony_ci	if (!(levels & NTFS_LOG_LEVEL_QUIET))
268987da915Sopenharmony_ci		opts.quiet++;
269987da915Sopenharmony_ci
270987da915Sopenharmony_ci	if (help || ver) {
271987da915Sopenharmony_ci		opts.quiet = 0;
272987da915Sopenharmony_ci	} else {
273987da915Sopenharmony_ci		if (opts.device == NULL) {
274987da915Sopenharmony_ci			if (argc > 1)
275987da915Sopenharmony_ci				ntfs_log_error("You must specify exactly one "
276987da915Sopenharmony_ci					"device.\n");
277987da915Sopenharmony_ci			err++;
278987da915Sopenharmony_ci		}
279987da915Sopenharmony_ci
280987da915Sopenharmony_ci		if (opts.inode == -1 && !opts.filename && !opts.mft) {
281987da915Sopenharmony_ci			if (argc > 1)
282987da915Sopenharmony_ci				ntfs_log_error("You must specify an inode to "
283987da915Sopenharmony_ci					"learn about.\n");
284987da915Sopenharmony_ci			err++;
285987da915Sopenharmony_ci		}
286987da915Sopenharmony_ci
287987da915Sopenharmony_ci		if (opts.quiet && opts.verbose) {
288987da915Sopenharmony_ci			ntfs_log_error("You may not use --quiet and --verbose "
289987da915Sopenharmony_ci				"at the same time.\n");
290987da915Sopenharmony_ci			err++;
291987da915Sopenharmony_ci		}
292987da915Sopenharmony_ci
293987da915Sopenharmony_ci		if ((opts.inode != -1) && (opts.filename != NULL)) {
294987da915Sopenharmony_ci			if (argc > 1)
295987da915Sopenharmony_ci				ntfs_log_error("You may not specify --inode "
296987da915Sopenharmony_ci					"and --file together.\n");
297987da915Sopenharmony_ci			err++;
298987da915Sopenharmony_ci		}
299987da915Sopenharmony_ci
300987da915Sopenharmony_ci	}
301987da915Sopenharmony_ci
302987da915Sopenharmony_ci	if (ver)
303987da915Sopenharmony_ci		version();
304987da915Sopenharmony_ci	if (help || err)
305987da915Sopenharmony_ci		usage();
306987da915Sopenharmony_ci
307987da915Sopenharmony_ci		/* tri-state 0 : done, 1 : error, -1 : proceed */
308987da915Sopenharmony_ci	return (err ? 1 : (help || ver ? 0 : -1));
309987da915Sopenharmony_ci}
310987da915Sopenharmony_ci
311987da915Sopenharmony_ci
312987da915Sopenharmony_ci/* *************** utility functions ******************** */
313987da915Sopenharmony_ci/**
314987da915Sopenharmony_ci * ntfsinfo_time_to_str() -
315987da915Sopenharmony_ci * @sle_ntfs_clock:	on disk time format in 100ns units since 1st jan 1601
316987da915Sopenharmony_ci *			in little-endian format
317987da915Sopenharmony_ci *
318987da915Sopenharmony_ci * Return char* in a format 'Thu Jan  1 00:00:00 1970'.
319987da915Sopenharmony_ci * No need to free the returned memory.
320987da915Sopenharmony_ci *
321987da915Sopenharmony_ci * Example of usage:
322987da915Sopenharmony_ci *	char *time_str = ntfsinfo_time_to_str(
323987da915Sopenharmony_ci *			sle64_to_cpu(standard_attr->creation_time));
324987da915Sopenharmony_ci *	printf("\tFile Creation Time:\t %s", time_str);
325987da915Sopenharmony_ci */
326987da915Sopenharmony_cistatic char *ntfsinfo_time_to_str(const sle64 sle_ntfs_clock)
327987da915Sopenharmony_ci{
328987da915Sopenharmony_ci		/* JPA display timestamps in UTC */
329987da915Sopenharmony_ci	static const char *months[]
330987da915Sopenharmony_ci		= { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
331987da915Sopenharmony_ci		    "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" } ;
332987da915Sopenharmony_ci	static const char *wdays[]
333987da915Sopenharmony_ci		= { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" } ;
334987da915Sopenharmony_ci	static char str[50];
335987da915Sopenharmony_ci	long long stamp;
336987da915Sopenharmony_ci	u32 days;
337987da915Sopenharmony_ci	u32 seconds;
338987da915Sopenharmony_ci	unsigned int year;
339987da915Sopenharmony_ci	unsigned int wday;
340987da915Sopenharmony_ci	int mon;
341987da915Sopenharmony_ci	int cnt;
342987da915Sopenharmony_ci
343987da915Sopenharmony_ci	stamp = sle64_to_cpu(sle_ntfs_clock);
344987da915Sopenharmony_ci	days = (stamp/(86400*10000000LL)) & 0x7ffff;
345987da915Sopenharmony_ci	seconds = ((stamp/10000000LL)%86400) & 0x1ffff;
346987da915Sopenharmony_ci	wday = (days + 1)%7;
347987da915Sopenharmony_ci	year = 1601;
348987da915Sopenharmony_ci				/* periods of 400 years */
349987da915Sopenharmony_ci	cnt = days/146097;
350987da915Sopenharmony_ci	days -= 146097*cnt;
351987da915Sopenharmony_ci	year += 400*cnt;
352987da915Sopenharmony_ci				/* periods of 100 years */
353987da915Sopenharmony_ci	cnt = (3*days + 3)/109573;
354987da915Sopenharmony_ci	days -= 36524*cnt;
355987da915Sopenharmony_ci	year += 100*cnt;
356987da915Sopenharmony_ci				/* periods of 4 years */
357987da915Sopenharmony_ci	cnt = days/1461;
358987da915Sopenharmony_ci	days -= 1461*cnt;
359987da915Sopenharmony_ci	year += 4*cnt;
360987da915Sopenharmony_ci				/* periods of a single year */
361987da915Sopenharmony_ci	cnt = (3*days + 3)/1096;
362987da915Sopenharmony_ci	days -= 365*cnt;
363987da915Sopenharmony_ci	year += cnt;
364987da915Sopenharmony_ci
365987da915Sopenharmony_ci	if ((!(year % 100) ? (year % 400) : (year % 4))
366987da915Sopenharmony_ci		&& (days > 58)) days++;
367987da915Sopenharmony_ci	if (days > 59) {
368987da915Sopenharmony_ci		mon = (5*days + 161)/153;
369987da915Sopenharmony_ci		days -= (153*mon - 162)/5;
370987da915Sopenharmony_ci	} else {
371987da915Sopenharmony_ci		mon = days/31 + 1;
372987da915Sopenharmony_ci		days -= 31*(mon - 1) - 1;
373987da915Sopenharmony_ci	}
374987da915Sopenharmony_ci	snprintf(str, sizeof(str), "%3s %3s %2u %02u:%02u:%02u %4u UTC\n",
375987da915Sopenharmony_ci		wdays[wday],
376987da915Sopenharmony_ci		months[mon-1],(unsigned int)days,
377987da915Sopenharmony_ci		(unsigned int)(seconds/3600),
378987da915Sopenharmony_ci		(unsigned int)(seconds/60%60),
379987da915Sopenharmony_ci		(unsigned int)(seconds%60),
380987da915Sopenharmony_ci		(unsigned int)year);
381987da915Sopenharmony_ci	return (str);
382987da915Sopenharmony_ci}
383987da915Sopenharmony_ci
384987da915Sopenharmony_ci/**
385987da915Sopenharmony_ci * ntfs_attr_get_name()
386987da915Sopenharmony_ci * @attr:	a valid attribute record
387987da915Sopenharmony_ci *
388987da915Sopenharmony_ci * return multi-byte string containing the attribute name if exist. the user
389987da915Sopenharmony_ci *             is then responsible of freeing that memory.
390987da915Sopenharmony_ci *        null if no name exists (attr->name_length==0). no memory allocated.
391987da915Sopenharmony_ci *        null if cannot convert to multi-byte string. errno would contain the
392987da915Sopenharmony_ci *             error id. no memory allocated in that case
393987da915Sopenharmony_ci */
394987da915Sopenharmony_cistatic char *ntfs_attr_get_name_mbs(ATTR_RECORD *attr)
395987da915Sopenharmony_ci{
396987da915Sopenharmony_ci	ntfschar *ucs_attr_name;
397987da915Sopenharmony_ci	char *mbs_attr_name = NULL;
398987da915Sopenharmony_ci	int mbs_attr_name_size;
399987da915Sopenharmony_ci
400987da915Sopenharmony_ci	/* Get name in unicode. */
401987da915Sopenharmony_ci	ucs_attr_name = ntfs_attr_get_name(attr);
402987da915Sopenharmony_ci	/* Convert unicode to printable format. */
403987da915Sopenharmony_ci	mbs_attr_name_size = ntfs_ucstombs(ucs_attr_name, attr->name_length,
404987da915Sopenharmony_ci			&mbs_attr_name, 0);
405987da915Sopenharmony_ci	if (mbs_attr_name_size > 0)
406987da915Sopenharmony_ci		return mbs_attr_name;
407987da915Sopenharmony_ci	else
408987da915Sopenharmony_ci		return NULL;
409987da915Sopenharmony_ci}
410987da915Sopenharmony_ci
411987da915Sopenharmony_cistatic const char *reparse_type_name(le32 tag)
412987da915Sopenharmony_ci{
413987da915Sopenharmony_ci	const char *name;
414987da915Sopenharmony_ci	le32 seltag;
415987da915Sopenharmony_ci
416987da915Sopenharmony_ci	seltag = tag & IO_REPARSE_PLUGIN_SELECT;
417987da915Sopenharmony_ci	switch (seltag) {
418987da915Sopenharmony_ci	case IO_REPARSE_TAG_MOUNT_POINT :
419987da915Sopenharmony_ci		name = " (mount point)";
420987da915Sopenharmony_ci		break;
421987da915Sopenharmony_ci	case IO_REPARSE_TAG_SYMLINK :
422987da915Sopenharmony_ci		name = " (symlink)";
423987da915Sopenharmony_ci		break;
424987da915Sopenharmony_ci	case IO_REPARSE_TAG_WOF :
425987da915Sopenharmony_ci		name = " (Wof compressed)";
426987da915Sopenharmony_ci		break;
427987da915Sopenharmony_ci	case IO_REPARSE_TAG_DEDUP :
428987da915Sopenharmony_ci		name = " (deduplicated)";
429987da915Sopenharmony_ci		break;
430987da915Sopenharmony_ci	case IO_REPARSE_TAG_WCI :
431987da915Sopenharmony_ci		name = " (Windows container)";
432987da915Sopenharmony_ci		break;
433987da915Sopenharmony_ci	case IO_REPARSE_TAG_CLOUD :
434987da915Sopenharmony_ci		name = " (Cloud)";
435987da915Sopenharmony_ci		break;
436987da915Sopenharmony_ci	case IO_REPARSE_TAG_NFS :
437987da915Sopenharmony_ci		name = " (NFS symlink)";
438987da915Sopenharmony_ci		break;
439987da915Sopenharmony_ci	case IO_REPARSE_TAG_LX_SYMLINK :
440987da915Sopenharmony_ci		name = " (Linux symlink)";
441987da915Sopenharmony_ci		break;
442987da915Sopenharmony_ci	case IO_REPARSE_TAG_LX_FIFO :
443987da915Sopenharmony_ci		name = " (Linux fifo)";
444987da915Sopenharmony_ci		break;
445987da915Sopenharmony_ci	case IO_REPARSE_TAG_LX_CHR :
446987da915Sopenharmony_ci		name = " (Linux character device)";
447987da915Sopenharmony_ci		break;
448987da915Sopenharmony_ci	case IO_REPARSE_TAG_LX_BLK :
449987da915Sopenharmony_ci		name = " (Linux block device)";
450987da915Sopenharmony_ci		break;
451987da915Sopenharmony_ci	case IO_REPARSE_TAG_AF_UNIX :
452987da915Sopenharmony_ci		name = " (Unix socket)";
453987da915Sopenharmony_ci		break;
454987da915Sopenharmony_ci	case IO_REPARSE_TAG_APPEXECLINK :
455987da915Sopenharmony_ci		name = " (Exec link)";
456987da915Sopenharmony_ci		break;
457987da915Sopenharmony_ci	default :
458987da915Sopenharmony_ci		name = "";
459987da915Sopenharmony_ci		break;
460987da915Sopenharmony_ci	}
461987da915Sopenharmony_ci	return (name);
462987da915Sopenharmony_ci}
463987da915Sopenharmony_ci
464987da915Sopenharmony_ci/* *************** functions for dumping global info ******************** */
465987da915Sopenharmony_ci/**
466987da915Sopenharmony_ci * ntfs_dump_volume - dump information about the volume
467987da915Sopenharmony_ci */
468987da915Sopenharmony_cistatic void ntfs_dump_volume(ntfs_volume *vol)
469987da915Sopenharmony_ci{
470987da915Sopenharmony_ci	printf("Volume Information \n");
471987da915Sopenharmony_ci	printf("\tName of device: %s\n", vol->dev->d_name);
472987da915Sopenharmony_ci	printf("\tDevice state: %lu\n", vol->dev->d_state);
473987da915Sopenharmony_ci	printf("\tVolume Name: %s\n", vol->vol_name);
474987da915Sopenharmony_ci	printf("\tVolume State: %lu\n", vol->state);
475987da915Sopenharmony_ci	printf("\tVolume Flags: 0x%04x", (int)le16_to_cpu(vol->flags));
476987da915Sopenharmony_ci	if (vol->flags & VOLUME_IS_DIRTY)
477987da915Sopenharmony_ci		printf(" DIRTY");
478987da915Sopenharmony_ci	if (vol->flags & VOLUME_MODIFIED_BY_CHKDSK)
479987da915Sopenharmony_ci		printf(" MODIFIED_BY_CHKDSK");
480987da915Sopenharmony_ci	printf("\n");
481987da915Sopenharmony_ci	printf("\tVolume Version: %u.%u\n", vol->major_ver, vol->minor_ver);
482987da915Sopenharmony_ci	printf("\tSector Size: %hu\n", vol->sector_size);
483987da915Sopenharmony_ci	printf("\tCluster Size: %u\n", (unsigned int)vol->cluster_size);
484987da915Sopenharmony_ci	printf("\tIndex Block Size: %u\n", (unsigned int)vol->indx_record_size);
485987da915Sopenharmony_ci	printf("\tVolume Size in Clusters: %lld\n",
486987da915Sopenharmony_ci			(long long)vol->nr_clusters);
487987da915Sopenharmony_ci
488987da915Sopenharmony_ci	printf("MFT Information \n");
489987da915Sopenharmony_ci	printf("\tMFT Record Size: %u\n", (unsigned int)vol->mft_record_size);
490987da915Sopenharmony_ci	printf("\tMFT Zone Multiplier: %u\n", vol->mft_zone_multiplier);
491987da915Sopenharmony_ci	printf("\tMFT Data Position: %lld\n", (long long)vol->mft_data_pos);
492987da915Sopenharmony_ci	printf("\tMFT Zone Start: %lld\n", (long long)vol->mft_zone_start);
493987da915Sopenharmony_ci	printf("\tMFT Zone End: %lld\n", (long long)vol->mft_zone_end);
494987da915Sopenharmony_ci	printf("\tMFT Zone Position: %lld\n", (long long)vol->mft_zone_pos);
495987da915Sopenharmony_ci	printf("\tCurrent Position in First Data Zone: %lld\n",
496987da915Sopenharmony_ci			(long long)vol->data1_zone_pos);
497987da915Sopenharmony_ci	printf("\tCurrent Position in Second Data Zone: %lld\n",
498987da915Sopenharmony_ci			(long long)vol->data2_zone_pos);
499987da915Sopenharmony_ci	printf("\tAllocated clusters %lld (%2.1lf%%)\n",
500987da915Sopenharmony_ci			(long long)vol->mft_na->allocated_size
501987da915Sopenharmony_ci				>> vol->cluster_size_bits,
502987da915Sopenharmony_ci			100.0*(vol->mft_na->allocated_size
503987da915Sopenharmony_ci				>> vol->cluster_size_bits)
504987da915Sopenharmony_ci				/ vol->nr_clusters);
505987da915Sopenharmony_ci	printf("\tLCN of Data Attribute for FILE_MFT: %lld\n",
506987da915Sopenharmony_ci			(long long)vol->mft_lcn);
507987da915Sopenharmony_ci	printf("\tFILE_MFTMirr Size: %d\n", vol->mftmirr_size);
508987da915Sopenharmony_ci	printf("\tLCN of Data Attribute for File_MFTMirr: %lld\n",
509987da915Sopenharmony_ci			(long long)vol->mftmirr_lcn);
510987da915Sopenharmony_ci	printf("\tSize of Attribute Definition Table: %d\n",
511987da915Sopenharmony_ci			(int)vol->attrdef_len);
512987da915Sopenharmony_ci	printf("\tNumber of Attached Extent Inodes: %d\n",
513987da915Sopenharmony_ci			(int)vol->mft_ni->nr_extents);
514987da915Sopenharmony_ci
515987da915Sopenharmony_ci	printf("FILE_Bitmap Information \n");
516987da915Sopenharmony_ci	printf("\tFILE_Bitmap MFT Record Number: %llu\n",
517987da915Sopenharmony_ci			(unsigned long long)vol->lcnbmp_ni->mft_no);
518987da915Sopenharmony_ci	printf("\tState of FILE_Bitmap Inode: %lu\n", vol->lcnbmp_ni->state);
519987da915Sopenharmony_ci	printf("\tLength of Attribute List: %u\n",
520987da915Sopenharmony_ci			(unsigned int)vol->lcnbmp_ni->attr_list_size);
521987da915Sopenharmony_ci	/* JPA	printf("\tAttribute List: %s\n", vol->lcnbmp_ni->attr_list); */
522987da915Sopenharmony_ci	printf("\tNumber of Attached Extent Inodes: %d\n",
523987da915Sopenharmony_ci			(int)vol->lcnbmp_ni->nr_extents);
524987da915Sopenharmony_ci	/* FIXME: need to add code for the union if nr_extens != 0, but
525987da915Sopenharmony_ci	   i dont know if it will ever != 0 with FILE_Bitmap */
526987da915Sopenharmony_ci
527987da915Sopenharmony_ci	printf("FILE_Bitmap Data Attribute Information\n");
528987da915Sopenharmony_ci	printf("\tDecompressed Runlist: not done yet\n");
529987da915Sopenharmony_ci	printf("\tBase Inode: %llu\n",
530987da915Sopenharmony_ci			(unsigned long long)vol->lcnbmp_na->ni->mft_no);
531987da915Sopenharmony_ci	printf("\tAttribute Types: not done yet\n");
532987da915Sopenharmony_ci	//printf("\tAttribute Name: %s\n", vol->lcnbmp_na->name);
533987da915Sopenharmony_ci	printf("\tAttribute Name Length: %u\n",
534987da915Sopenharmony_ci			(unsigned int)vol->lcnbmp_na->name_len);
535987da915Sopenharmony_ci	printf("\tAttribute State: %lu\n", vol->lcnbmp_na->state);
536987da915Sopenharmony_ci	printf("\tAttribute Allocated Size: %lld\n",
537987da915Sopenharmony_ci			(long long)vol->lcnbmp_na->allocated_size);
538987da915Sopenharmony_ci	printf("\tAttribute Data Size: %lld\n",
539987da915Sopenharmony_ci			(long long)vol->lcnbmp_na->data_size);
540987da915Sopenharmony_ci	printf("\tAttribute Initialized Size: %lld\n",
541987da915Sopenharmony_ci			(long long)vol->lcnbmp_na->initialized_size);
542987da915Sopenharmony_ci	printf("\tAttribute Compressed Size: %lld\n",
543987da915Sopenharmony_ci			(long long)vol->lcnbmp_na->compressed_size);
544987da915Sopenharmony_ci	printf("\tCompression Block Size: %u\n",
545987da915Sopenharmony_ci			(unsigned int)vol->lcnbmp_na->compression_block_size);
546987da915Sopenharmony_ci	printf("\tCompression Block Size Bits: %u\n",
547987da915Sopenharmony_ci			vol->lcnbmp_na->compression_block_size_bits);
548987da915Sopenharmony_ci	printf("\tCompression Block Clusters: %u\n",
549987da915Sopenharmony_ci			vol->lcnbmp_na->compression_block_clusters);
550987da915Sopenharmony_ci	if (!ntfs_volume_get_free_space(vol))
551987da915Sopenharmony_ci		printf("\tFree Clusters: %lld (%2.1lf%%)\n",
552987da915Sopenharmony_ci				(long long)vol->free_clusters,
553987da915Sopenharmony_ci				100.0*vol->free_clusters
554987da915Sopenharmony_ci					/(double)vol->nr_clusters);
555987da915Sopenharmony_ci
556987da915Sopenharmony_ci	//TODO: Still need to add a few more attributes
557987da915Sopenharmony_ci}
558987da915Sopenharmony_ci
559987da915Sopenharmony_ci/**
560987da915Sopenharmony_ci * ntfs_dump_flags - Dump flags for STANDARD_INFORMATION and FILE_NAME.
561987da915Sopenharmony_ci * @type:	dump flags for this attribute type
562987da915Sopenharmony_ci * @flags:	flags for dumping
563987da915Sopenharmony_ci */
564987da915Sopenharmony_cistatic void ntfs_dump_flags(const char *indent, ATTR_TYPES type, le32 flags)
565987da915Sopenharmony_ci{
566987da915Sopenharmony_ci	const le32 original_flags = flags;
567987da915Sopenharmony_ci
568987da915Sopenharmony_ci	printf("%sFile attributes:\t", indent);
569987da915Sopenharmony_ci	if (flags & FILE_ATTR_READONLY) {
570987da915Sopenharmony_ci		printf(" READONLY");
571987da915Sopenharmony_ci		flags &= ~FILE_ATTR_READONLY;
572987da915Sopenharmony_ci	}
573987da915Sopenharmony_ci	if (flags & FILE_ATTR_HIDDEN) {
574987da915Sopenharmony_ci		printf(" HIDDEN");
575987da915Sopenharmony_ci		flags &= ~FILE_ATTR_HIDDEN;
576987da915Sopenharmony_ci	}
577987da915Sopenharmony_ci	if (flags & FILE_ATTR_SYSTEM) {
578987da915Sopenharmony_ci		printf(" SYSTEM");
579987da915Sopenharmony_ci		flags &= ~FILE_ATTR_SYSTEM;
580987da915Sopenharmony_ci	}
581987da915Sopenharmony_ci	if (flags & FILE_ATTR_DIRECTORY) {
582987da915Sopenharmony_ci		printf(" DIRECTORY");
583987da915Sopenharmony_ci		flags &= ~FILE_ATTR_DIRECTORY;
584987da915Sopenharmony_ci	}
585987da915Sopenharmony_ci	if (flags & FILE_ATTR_ARCHIVE) {
586987da915Sopenharmony_ci		printf(" ARCHIVE");
587987da915Sopenharmony_ci		flags &= ~FILE_ATTR_ARCHIVE;
588987da915Sopenharmony_ci	}
589987da915Sopenharmony_ci	if (flags & FILE_ATTR_DEVICE) {
590987da915Sopenharmony_ci		printf(" DEVICE");
591987da915Sopenharmony_ci		flags &= ~FILE_ATTR_DEVICE;
592987da915Sopenharmony_ci	}
593987da915Sopenharmony_ci	if (flags & FILE_ATTR_NORMAL) {
594987da915Sopenharmony_ci		printf(" NORMAL");
595987da915Sopenharmony_ci		flags &= ~FILE_ATTR_NORMAL;
596987da915Sopenharmony_ci	}
597987da915Sopenharmony_ci	if (flags & FILE_ATTR_TEMPORARY) {
598987da915Sopenharmony_ci		printf(" TEMPORARY");
599987da915Sopenharmony_ci		flags &= ~FILE_ATTR_TEMPORARY;
600987da915Sopenharmony_ci	}
601987da915Sopenharmony_ci	if (flags & FILE_ATTR_SPARSE_FILE) {
602987da915Sopenharmony_ci		printf(" SPARSE_FILE");
603987da915Sopenharmony_ci		flags &= ~FILE_ATTR_SPARSE_FILE;
604987da915Sopenharmony_ci	}
605987da915Sopenharmony_ci	if (flags & FILE_ATTR_REPARSE_POINT) {
606987da915Sopenharmony_ci		printf(" REPARSE_POINT");
607987da915Sopenharmony_ci		flags &= ~FILE_ATTR_REPARSE_POINT;
608987da915Sopenharmony_ci	}
609987da915Sopenharmony_ci	if (flags & FILE_ATTR_COMPRESSED) {
610987da915Sopenharmony_ci		printf(" COMPRESSED");
611987da915Sopenharmony_ci		flags &= ~FILE_ATTR_COMPRESSED;
612987da915Sopenharmony_ci	}
613987da915Sopenharmony_ci	if (flags & FILE_ATTR_OFFLINE) {
614987da915Sopenharmony_ci		printf(" OFFLINE");
615987da915Sopenharmony_ci		flags &= ~FILE_ATTR_OFFLINE;
616987da915Sopenharmony_ci	}
617987da915Sopenharmony_ci	if (flags & FILE_ATTR_NOT_CONTENT_INDEXED) {
618987da915Sopenharmony_ci		printf(" NOT_CONTENT_INDEXED");
619987da915Sopenharmony_ci		flags &= ~FILE_ATTR_NOT_CONTENT_INDEXED;
620987da915Sopenharmony_ci	}
621987da915Sopenharmony_ci	if (flags & FILE_ATTR_ENCRYPTED) {
622987da915Sopenharmony_ci		printf(" ENCRYPTED");
623987da915Sopenharmony_ci		flags &= ~FILE_ATTR_ENCRYPTED;
624987da915Sopenharmony_ci	}
625987da915Sopenharmony_ci	/* We know that FILE_ATTR_I30_INDEX_PRESENT only exists on $FILE_NAME,
626987da915Sopenharmony_ci	   and in case we are wrong, let it appear as UNKNOWN */
627987da915Sopenharmony_ci	if (type == AT_FILE_NAME) {
628987da915Sopenharmony_ci		if (flags & FILE_ATTR_I30_INDEX_PRESENT) {
629987da915Sopenharmony_ci			printf(" I30_INDEX");
630987da915Sopenharmony_ci			flags &= ~FILE_ATTR_I30_INDEX_PRESENT;
631987da915Sopenharmony_ci		}
632987da915Sopenharmony_ci	}
633987da915Sopenharmony_ci	if (flags & FILE_ATTR_VIEW_INDEX_PRESENT) {
634987da915Sopenharmony_ci		printf(" VIEW_INDEX");
635987da915Sopenharmony_ci		flags &= ~FILE_ATTR_VIEW_INDEX_PRESENT;
636987da915Sopenharmony_ci	}
637987da915Sopenharmony_ci	if (flags & FILE_ATTRIBUTE_RECALL_ON_OPEN) {
638987da915Sopenharmony_ci		printf(" RECALL_ON_OPEN");
639987da915Sopenharmony_ci		flags &= ~FILE_ATTRIBUTE_RECALL_ON_OPEN;
640987da915Sopenharmony_ci	}
641987da915Sopenharmony_ci	if (flags)
642987da915Sopenharmony_ci		printf(" UNKNOWN: 0x%08x", (unsigned int)le32_to_cpu(flags));
643987da915Sopenharmony_ci	/* Print all the flags in hex. */
644987da915Sopenharmony_ci	printf(" (0x%08x)\n", (unsigned)le32_to_cpu(original_flags));
645987da915Sopenharmony_ci}
646987da915Sopenharmony_ci
647987da915Sopenharmony_ci/**
648987da915Sopenharmony_ci * ntfs_dump_namespace
649987da915Sopenharmony_ci */
650987da915Sopenharmony_cistatic void ntfs_dump_namespace(const char *indent, u8 file_name_type)
651987da915Sopenharmony_ci{
652987da915Sopenharmony_ci	const char *mbs_file_type;
653987da915Sopenharmony_ci
654987da915Sopenharmony_ci	/* name space */
655987da915Sopenharmony_ci	switch (file_name_type) {
656987da915Sopenharmony_ci	case FILE_NAME_POSIX:
657987da915Sopenharmony_ci		mbs_file_type = "POSIX";
658987da915Sopenharmony_ci		break;
659987da915Sopenharmony_ci	case FILE_NAME_WIN32:
660987da915Sopenharmony_ci		mbs_file_type = "Win32";
661987da915Sopenharmony_ci		break;
662987da915Sopenharmony_ci	case FILE_NAME_DOS:
663987da915Sopenharmony_ci		mbs_file_type = "DOS";
664987da915Sopenharmony_ci		break;
665987da915Sopenharmony_ci	case FILE_NAME_WIN32_AND_DOS:
666987da915Sopenharmony_ci		mbs_file_type = "Win32 & DOS";
667987da915Sopenharmony_ci		break;
668987da915Sopenharmony_ci	default:
669987da915Sopenharmony_ci		mbs_file_type = "(unknown)";
670987da915Sopenharmony_ci	}
671987da915Sopenharmony_ci	printf("%sNamespace:\t\t %s\n", indent, mbs_file_type);
672987da915Sopenharmony_ci}
673987da915Sopenharmony_ci
674987da915Sopenharmony_ci/* *************** functions for dumping attributes ******************** */
675987da915Sopenharmony_ci/**
676987da915Sopenharmony_ci * ntfs_dump_standard_information
677987da915Sopenharmony_ci */
678987da915Sopenharmony_cistatic void ntfs_dump_attr_standard_information(ATTR_RECORD *attr)
679987da915Sopenharmony_ci{
680987da915Sopenharmony_ci	STANDARD_INFORMATION *standard_attr = NULL;
681987da915Sopenharmony_ci	u32 value_length;
682987da915Sopenharmony_ci
683987da915Sopenharmony_ci	standard_attr = (STANDARD_INFORMATION*)((char *)attr +
684987da915Sopenharmony_ci		le16_to_cpu(attr->value_offset));
685987da915Sopenharmony_ci
686987da915Sopenharmony_ci	/* time conversion stuff */
687987da915Sopenharmony_ci	if (!opts.notime) {
688987da915Sopenharmony_ci		char *ntfs_time_str = NULL;
689987da915Sopenharmony_ci
690987da915Sopenharmony_ci		ntfs_time_str = ntfsinfo_time_to_str(standard_attr->creation_time);
691987da915Sopenharmony_ci		printf("\tFile Creation Time:\t %s",ntfs_time_str);
692987da915Sopenharmony_ci
693987da915Sopenharmony_ci		ntfs_time_str = ntfsinfo_time_to_str(
694987da915Sopenharmony_ci			standard_attr->last_data_change_time);
695987da915Sopenharmony_ci		printf("\tFile Altered Time:\t %s",ntfs_time_str);
696987da915Sopenharmony_ci
697987da915Sopenharmony_ci		ntfs_time_str = ntfsinfo_time_to_str(
698987da915Sopenharmony_ci			standard_attr->last_mft_change_time);
699987da915Sopenharmony_ci		printf("\tMFT Changed Time:\t %s",ntfs_time_str);
700987da915Sopenharmony_ci
701987da915Sopenharmony_ci		ntfs_time_str = ntfsinfo_time_to_str(standard_attr->last_access_time);
702987da915Sopenharmony_ci		printf("\tLast Accessed Time:\t %s",ntfs_time_str);
703987da915Sopenharmony_ci	}
704987da915Sopenharmony_ci	ntfs_dump_flags("\t", attr->type, standard_attr->file_attributes);
705987da915Sopenharmony_ci
706987da915Sopenharmony_ci	value_length = le32_to_cpu(attr->value_length);
707987da915Sopenharmony_ci	if (value_length == 48) {
708987da915Sopenharmony_ci		/* Only 12 reserved bytes here */
709987da915Sopenharmony_ci	} else if (value_length == 72) {
710987da915Sopenharmony_ci		printf("\tMaximum versions:\t %u \n", (unsigned int)
711987da915Sopenharmony_ci				le32_to_cpu(standard_attr->maximum_versions));
712987da915Sopenharmony_ci		printf("\tVersion number:\t\t %u \n", (unsigned int)
713987da915Sopenharmony_ci				le32_to_cpu(standard_attr->version_number));
714987da915Sopenharmony_ci		printf("\tClass ID:\t\t %u \n",
715987da915Sopenharmony_ci			(unsigned int)le32_to_cpu(standard_attr->class_id));
716987da915Sopenharmony_ci		printf("\tUser ID:\t\t %u (0x%x)\n",
717987da915Sopenharmony_ci			(unsigned int)le32_to_cpu(standard_attr->owner_id),
718987da915Sopenharmony_ci			(unsigned int)le32_to_cpu(standard_attr->owner_id));
719987da915Sopenharmony_ci		printf("\tSecurity ID:\t\t %u (0x%x)\n",
720987da915Sopenharmony_ci			(unsigned int)le32_to_cpu(standard_attr->security_id),
721987da915Sopenharmony_ci			(unsigned int)le32_to_cpu(standard_attr->security_id));
722987da915Sopenharmony_ci		printf("\tQuota charged:\t\t %llu (0x%llx)\n",
723987da915Sopenharmony_ci				(unsigned long long)
724987da915Sopenharmony_ci				le64_to_cpu(standard_attr->quota_charged),
725987da915Sopenharmony_ci				(unsigned long long)
726987da915Sopenharmony_ci				le64_to_cpu(standard_attr->quota_charged));
727987da915Sopenharmony_ci		printf("\tUpdate Sequence Number:\t %llu (0x%llx)\n",
728987da915Sopenharmony_ci				(unsigned long long)
729987da915Sopenharmony_ci				le64_to_cpu(standard_attr->usn),
730987da915Sopenharmony_ci				(unsigned long long)
731987da915Sopenharmony_ci				le64_to_cpu(standard_attr->usn));
732987da915Sopenharmony_ci	} else {
733987da915Sopenharmony_ci		printf("\tSize of STANDARD_INFORMATION is %u (0x%x).  It "
734987da915Sopenharmony_ci				"should be either 72 or 48, something is "
735987da915Sopenharmony_ci				"wrong...\n", (unsigned int)value_length,
736987da915Sopenharmony_ci				(unsigned)value_length);
737987da915Sopenharmony_ci	}
738987da915Sopenharmony_ci}
739987da915Sopenharmony_ci
740987da915Sopenharmony_cistatic void ntfs_dump_bytes(u8 *buf, int start, int stop)
741987da915Sopenharmony_ci{
742987da915Sopenharmony_ci	int i;
743987da915Sopenharmony_ci
744987da915Sopenharmony_ci	for (i = start; i < stop; i++) {
745987da915Sopenharmony_ci		printf("%02x ", buf[i]);
746987da915Sopenharmony_ci	}
747987da915Sopenharmony_ci}
748987da915Sopenharmony_ci
749987da915Sopenharmony_ci/**
750987da915Sopenharmony_ci * ntfs_dump_attr_list()
751987da915Sopenharmony_ci */
752987da915Sopenharmony_cistatic void ntfs_dump_attr_list(ATTR_RECORD *attr, ntfs_volume *vol)
753987da915Sopenharmony_ci{
754987da915Sopenharmony_ci	ATTR_LIST_ENTRY *entry;
755987da915Sopenharmony_ci	u8 *value;
756987da915Sopenharmony_ci	s64 l;
757987da915Sopenharmony_ci
758987da915Sopenharmony_ci	if (!opts.verbose)
759987da915Sopenharmony_ci		return;
760987da915Sopenharmony_ci
761987da915Sopenharmony_ci	l = ntfs_get_attribute_value_length(attr);
762987da915Sopenharmony_ci	if (!l) {
763987da915Sopenharmony_ci		ntfs_log_perror("ntfs_get_attribute_value_length failed");
764987da915Sopenharmony_ci		return;
765987da915Sopenharmony_ci	}
766987da915Sopenharmony_ci	value = ntfs_malloc(l);
767987da915Sopenharmony_ci	if (!value)
768987da915Sopenharmony_ci		return;
769987da915Sopenharmony_ci
770987da915Sopenharmony_ci	l = ntfs_get_attribute_value(vol, attr, value);
771987da915Sopenharmony_ci	if (!l) {
772987da915Sopenharmony_ci		ntfs_log_perror("ntfs_get_attribute_value failed");
773987da915Sopenharmony_ci		free(value);
774987da915Sopenharmony_ci		return;
775987da915Sopenharmony_ci	}
776987da915Sopenharmony_ci	printf("\tDumping attribute list:");
777987da915Sopenharmony_ci	entry = (ATTR_LIST_ENTRY *) value;
778987da915Sopenharmony_ci	for (;(u8 *)entry < (u8 *) value + l; entry = (ATTR_LIST_ENTRY *)
779987da915Sopenharmony_ci				((u8 *) entry + le16_to_cpu(entry->length))) {
780987da915Sopenharmony_ci		printf("\n");
781987da915Sopenharmony_ci		printf("\t\tAttribute type:\t0x%x\n",
782987da915Sopenharmony_ci				(unsigned int)le32_to_cpu(entry->type));
783987da915Sopenharmony_ci		printf("\t\tRecord length:\t%u (0x%x)\n",
784987da915Sopenharmony_ci				(unsigned)le16_to_cpu(entry->length),
785987da915Sopenharmony_ci				(unsigned)le16_to_cpu(entry->length));
786987da915Sopenharmony_ci		printf("\t\tName length:\t%u (0x%x)\n",
787987da915Sopenharmony_ci				(unsigned)entry->name_length,
788987da915Sopenharmony_ci				(unsigned)entry->name_length);
789987da915Sopenharmony_ci		printf("\t\tName offset:\t%u (0x%x)\n",
790987da915Sopenharmony_ci				(unsigned)entry->name_offset,
791987da915Sopenharmony_ci				(unsigned)entry->name_offset);
792987da915Sopenharmony_ci		printf("\t\tStarting VCN:\t%lld (0x%llx)\n",
793987da915Sopenharmony_ci				(long long)sle64_to_cpu(entry->lowest_vcn),
794987da915Sopenharmony_ci				(unsigned long long)
795987da915Sopenharmony_ci				sle64_to_cpu(entry->lowest_vcn));
796987da915Sopenharmony_ci		printf("\t\tMFT reference:\t%lld (0x%llx)\n",
797987da915Sopenharmony_ci				(unsigned long long)
798987da915Sopenharmony_ci				MREF_LE(entry->mft_reference),
799987da915Sopenharmony_ci				(unsigned long long)
800987da915Sopenharmony_ci				MREF_LE(entry->mft_reference));
801987da915Sopenharmony_ci		printf("\t\tInstance:\t%u (0x%x)\n",
802987da915Sopenharmony_ci				(unsigned)le16_to_cpu(entry->instance),
803987da915Sopenharmony_ci				(unsigned)le16_to_cpu(entry->instance));
804987da915Sopenharmony_ci		printf("\t\tName:\t\t");
805987da915Sopenharmony_ci		if (entry->name_length) {
806987da915Sopenharmony_ci			char *name = NULL;
807987da915Sopenharmony_ci			int name_size;
808987da915Sopenharmony_ci
809987da915Sopenharmony_ci			name_size = ntfs_ucstombs(entry->name,
810987da915Sopenharmony_ci					entry->name_length, &name, 0);
811987da915Sopenharmony_ci
812987da915Sopenharmony_ci			if (name_size > 0) {
813987da915Sopenharmony_ci				printf("%s\n", name);
814987da915Sopenharmony_ci				free(name);
815987da915Sopenharmony_ci			} else
816987da915Sopenharmony_ci				ntfs_log_perror("ntfs_ucstombs failed");
817987da915Sopenharmony_ci		} else
818987da915Sopenharmony_ci			printf("unnamed\n");
819987da915Sopenharmony_ci		printf("\t\tPadding:\t");
820987da915Sopenharmony_ci		ntfs_dump_bytes((u8 *)entry, entry->name_offset +
821987da915Sopenharmony_ci				sizeof(ntfschar) * entry->name_length,
822987da915Sopenharmony_ci				le16_to_cpu(entry->length));
823987da915Sopenharmony_ci		printf("\n");
824987da915Sopenharmony_ci	}
825987da915Sopenharmony_ci	free(value);
826987da915Sopenharmony_ci	printf("\tEnd of attribute list reached.\n");
827987da915Sopenharmony_ci}
828987da915Sopenharmony_ci
829987da915Sopenharmony_ci/**
830987da915Sopenharmony_ci * ntfs_dump_filename()
831987da915Sopenharmony_ci */
832987da915Sopenharmony_cistatic void ntfs_dump_filename(const char *indent,
833987da915Sopenharmony_ci		FILE_NAME_ATTR *file_name_attr)
834987da915Sopenharmony_ci{
835987da915Sopenharmony_ci	le32 tag;
836987da915Sopenharmony_ci
837987da915Sopenharmony_ci	printf("%sParent directory:\t %lld (0x%llx)\n", indent,
838987da915Sopenharmony_ci			(long long)MREF_LE(file_name_attr->parent_directory),
839987da915Sopenharmony_ci			(long long)MREF_LE(file_name_attr->parent_directory));
840987da915Sopenharmony_ci	/* time stuff */
841987da915Sopenharmony_ci	if (!opts.notime) {
842987da915Sopenharmony_ci		char *ntfs_time_str;
843987da915Sopenharmony_ci
844987da915Sopenharmony_ci		ntfs_time_str = ntfsinfo_time_to_str(
845987da915Sopenharmony_ci				file_name_attr->creation_time);
846987da915Sopenharmony_ci		printf("%sFile Creation Time:\t %s", indent, ntfs_time_str);
847987da915Sopenharmony_ci
848987da915Sopenharmony_ci		ntfs_time_str = ntfsinfo_time_to_str(
849987da915Sopenharmony_ci				file_name_attr->last_data_change_time);
850987da915Sopenharmony_ci		printf("%sFile Altered Time:\t %s", indent, ntfs_time_str);
851987da915Sopenharmony_ci
852987da915Sopenharmony_ci		ntfs_time_str = ntfsinfo_time_to_str(
853987da915Sopenharmony_ci				file_name_attr->last_mft_change_time);
854987da915Sopenharmony_ci		printf("%sMFT Changed Time:\t %s", indent, ntfs_time_str);
855987da915Sopenharmony_ci
856987da915Sopenharmony_ci		ntfs_time_str = ntfsinfo_time_to_str(
857987da915Sopenharmony_ci				file_name_attr->last_access_time);
858987da915Sopenharmony_ci		printf("%sLast Accessed Time:\t %s", indent, ntfs_time_str);
859987da915Sopenharmony_ci	}
860987da915Sopenharmony_ci	/* other basic stuff about the file */
861987da915Sopenharmony_ci	printf("%sAllocated Size:\t\t %lld (0x%llx)\n", indent, (long long)
862987da915Sopenharmony_ci			sle64_to_cpu(file_name_attr->allocated_size),
863987da915Sopenharmony_ci			(unsigned long long)
864987da915Sopenharmony_ci			sle64_to_cpu(file_name_attr->allocated_size));
865987da915Sopenharmony_ci	printf("%sData Size:\t\t %lld (0x%llx)\n", indent,
866987da915Sopenharmony_ci			(long long)sle64_to_cpu(file_name_attr->data_size),
867987da915Sopenharmony_ci			(unsigned long long)
868987da915Sopenharmony_ci			sle64_to_cpu(file_name_attr->data_size));
869987da915Sopenharmony_ci	printf("%sFilename Length:\t %d (0x%x)\n", indent,
870987da915Sopenharmony_ci			(unsigned)file_name_attr->file_name_length,
871987da915Sopenharmony_ci			(unsigned)file_name_attr->file_name_length);
872987da915Sopenharmony_ci	ntfs_dump_flags(indent, AT_FILE_NAME, file_name_attr->file_attributes);
873987da915Sopenharmony_ci	if (file_name_attr->file_attributes & FILE_ATTR_REPARSE_POINT &&
874987da915Sopenharmony_ci			file_name_attr->reparse_point_tag) {
875987da915Sopenharmony_ci		tag = file_name_attr->reparse_point_tag;
876987da915Sopenharmony_ci		printf("%sReparse point tag:\t 0x%08lx%s\n", indent,
877987da915Sopenharmony_ci				(long)le32_to_cpu(tag),
878987da915Sopenharmony_ci				reparse_type_name(tag));
879987da915Sopenharmony_ci	} else if (file_name_attr->reparse_point_tag) {
880987da915Sopenharmony_ci		printf("%sEA Length:\t\t %d (0x%x)\n", indent, (unsigned)
881987da915Sopenharmony_ci				le16_to_cpu(file_name_attr->packed_ea_size),
882987da915Sopenharmony_ci				(unsigned)
883987da915Sopenharmony_ci				le16_to_cpu(file_name_attr->packed_ea_size));
884987da915Sopenharmony_ci		if (file_name_attr->reserved)
885987da915Sopenharmony_ci			printf("%sReserved:\t\t %d (0x%x)\n", indent,
886987da915Sopenharmony_ci					(unsigned)
887987da915Sopenharmony_ci					le16_to_cpu(file_name_attr->reserved),
888987da915Sopenharmony_ci					(unsigned)
889987da915Sopenharmony_ci					le16_to_cpu(file_name_attr->reserved));
890987da915Sopenharmony_ci	}
891987da915Sopenharmony_ci	/* The filename. */
892987da915Sopenharmony_ci	ntfs_dump_namespace(indent, file_name_attr->file_name_type);
893987da915Sopenharmony_ci	if (file_name_attr->file_name_length > 0) {
894987da915Sopenharmony_ci		/* but first we need to convert the little endian unicode string
895987da915Sopenharmony_ci		   into a printable format */
896987da915Sopenharmony_ci		char *mbs_file_name = NULL;
897987da915Sopenharmony_ci		int mbs_file_name_size;
898987da915Sopenharmony_ci
899987da915Sopenharmony_ci		mbs_file_name_size = ntfs_ucstombs(file_name_attr->file_name,
900987da915Sopenharmony_ci			file_name_attr->file_name_length,&mbs_file_name,0);
901987da915Sopenharmony_ci
902987da915Sopenharmony_ci		if (mbs_file_name_size>0) {
903987da915Sopenharmony_ci			printf("%sFilename:\t\t '%s'\n", indent, mbs_file_name);
904987da915Sopenharmony_ci			free(mbs_file_name);
905987da915Sopenharmony_ci		} else {
906987da915Sopenharmony_ci			/* an error occurred, errno holds the reason - notify the user */
907987da915Sopenharmony_ci			ntfs_log_perror("ntfsinfo error: could not parse file name");
908987da915Sopenharmony_ci		}
909987da915Sopenharmony_ci	} else {
910987da915Sopenharmony_ci		printf("%sFile Name:\t\t unnamed?!?\n", indent);
911987da915Sopenharmony_ci	}
912987da915Sopenharmony_ci}
913987da915Sopenharmony_ci
914987da915Sopenharmony_ci/**
915987da915Sopenharmony_ci * ntfs_dump_attr_file_name()
916987da915Sopenharmony_ci */
917987da915Sopenharmony_cistatic void ntfs_dump_attr_file_name(ATTR_RECORD *attr)
918987da915Sopenharmony_ci{
919987da915Sopenharmony_ci	ntfs_dump_filename("\t", (FILE_NAME_ATTR*)((u8*)attr +
920987da915Sopenharmony_ci			le16_to_cpu(attr->value_offset)));
921987da915Sopenharmony_ci}
922987da915Sopenharmony_ci
923987da915Sopenharmony_ci/**
924987da915Sopenharmony_ci * ntfs_dump_object_id
925987da915Sopenharmony_ci *
926987da915Sopenharmony_ci * dump the $OBJECT_ID attribute - not present on all systems
927987da915Sopenharmony_ci */
928987da915Sopenharmony_cistatic void ntfs_dump_attr_object_id(ATTR_RECORD *attr,ntfs_volume *vol)
929987da915Sopenharmony_ci{
930987da915Sopenharmony_ci	OBJECT_ID_ATTR *obj_id_attr = NULL;
931987da915Sopenharmony_ci
932987da915Sopenharmony_ci	obj_id_attr = (OBJECT_ID_ATTR *)((u8*)attr +
933987da915Sopenharmony_ci			le16_to_cpu(attr->value_offset));
934987da915Sopenharmony_ci
935987da915Sopenharmony_ci	if (vol->major_ver >= 3.0) {
936987da915Sopenharmony_ci		u32 value_length;
937987da915Sopenharmony_ci		char printable_GUID[37];
938987da915Sopenharmony_ci
939987da915Sopenharmony_ci		value_length = le32_to_cpu(attr->value_length);
940987da915Sopenharmony_ci
941987da915Sopenharmony_ci		/* Object ID is mandatory. */
942987da915Sopenharmony_ci		ntfs_guid_to_mbs(&obj_id_attr->object_id, printable_GUID);
943987da915Sopenharmony_ci		printf("\tObject ID:\t\t %s\n", printable_GUID);
944987da915Sopenharmony_ci
945987da915Sopenharmony_ci		/* Dump Birth Volume ID. */
946987da915Sopenharmony_ci		if ((value_length > sizeof(GUID)) && !ntfs_guid_is_zero(
947987da915Sopenharmony_ci				&obj_id_attr->birth_volume_id)) {
948987da915Sopenharmony_ci			ntfs_guid_to_mbs(&obj_id_attr->birth_volume_id,
949987da915Sopenharmony_ci					printable_GUID);
950987da915Sopenharmony_ci			printf("\tBirth Volume ID:\t\t %s\n", printable_GUID);
951987da915Sopenharmony_ci		} else
952987da915Sopenharmony_ci			printf("\tBirth Volume ID:\t missing\n");
953987da915Sopenharmony_ci
954987da915Sopenharmony_ci		/* Dumping Birth Object ID */
955987da915Sopenharmony_ci		if ((value_length > sizeof(GUID)) && !ntfs_guid_is_zero(
956987da915Sopenharmony_ci				&obj_id_attr->birth_object_id)) {
957987da915Sopenharmony_ci			ntfs_guid_to_mbs(&obj_id_attr->birth_object_id,
958987da915Sopenharmony_ci					printable_GUID);
959987da915Sopenharmony_ci			printf("\tBirth Object ID:\t\t %s\n", printable_GUID);
960987da915Sopenharmony_ci		} else
961987da915Sopenharmony_ci			printf("\tBirth Object ID:\t missing\n");
962987da915Sopenharmony_ci
963987da915Sopenharmony_ci		/* Dumping Domain_id - reserved for now */
964987da915Sopenharmony_ci		if ((value_length > sizeof(GUID)) && !ntfs_guid_is_zero(
965987da915Sopenharmony_ci				&obj_id_attr->domain_id)) {
966987da915Sopenharmony_ci			ntfs_guid_to_mbs(&obj_id_attr->domain_id,
967987da915Sopenharmony_ci					printable_GUID);
968987da915Sopenharmony_ci			printf("\tDomain ID:\t\t\t %s\n", printable_GUID);
969987da915Sopenharmony_ci		} else
970987da915Sopenharmony_ci			printf("\tDomain ID:\t\t missing\n");
971987da915Sopenharmony_ci	} else
972987da915Sopenharmony_ci		printf("\t$OBJECT_ID not present. Only NTFS versions > 3.0\n"
973987da915Sopenharmony_ci			"\thave $OBJECT_ID. Your version of NTFS is %d.\n",
974987da915Sopenharmony_ci				vol->major_ver);
975987da915Sopenharmony_ci}
976987da915Sopenharmony_ci
977987da915Sopenharmony_ci/**
978987da915Sopenharmony_ci * ntfs_dump_acl
979987da915Sopenharmony_ci *
980987da915Sopenharmony_ci * given an acl, print it in a beautiful & lovely way.
981987da915Sopenharmony_ci */
982987da915Sopenharmony_cistatic void ntfs_dump_acl(const char *prefix, ACL *acl)
983987da915Sopenharmony_ci{
984987da915Sopenharmony_ci	unsigned int i;
985987da915Sopenharmony_ci	u16 ace_count;
986987da915Sopenharmony_ci	ACCESS_ALLOWED_ACE *ace;
987987da915Sopenharmony_ci
988987da915Sopenharmony_ci	printf("%sRevision\t %u\n", prefix, acl->revision);
989987da915Sopenharmony_ci
990987da915Sopenharmony_ci	/*
991987da915Sopenharmony_ci	 * Do not recalculate le16_to_cpu every iteration (minor speedup on
992987da915Sopenharmony_ci	 * big-endian machines.
993987da915Sopenharmony_ci	 */
994987da915Sopenharmony_ci	ace_count = le16_to_cpu(acl->ace_count);
995987da915Sopenharmony_ci
996987da915Sopenharmony_ci	/* initialize 'ace' to the first ace (if any) */
997987da915Sopenharmony_ci	ace = (ACCESS_ALLOWED_ACE *)((char *)acl + 8);
998987da915Sopenharmony_ci
999987da915Sopenharmony_ci	/* iterate through ACE's */
1000987da915Sopenharmony_ci	for (i = 1; i <= ace_count; i++) {
1001987da915Sopenharmony_ci		const char *ace_type;
1002987da915Sopenharmony_ci		char *sid;
1003987da915Sopenharmony_ci
1004987da915Sopenharmony_ci		/* set ace_type. */
1005987da915Sopenharmony_ci		switch (ace->type) {
1006987da915Sopenharmony_ci		case ACCESS_ALLOWED_ACE_TYPE:
1007987da915Sopenharmony_ci			ace_type = "allow";
1008987da915Sopenharmony_ci			break;
1009987da915Sopenharmony_ci		case ACCESS_DENIED_ACE_TYPE:
1010987da915Sopenharmony_ci			ace_type = "deny";
1011987da915Sopenharmony_ci			break;
1012987da915Sopenharmony_ci		case SYSTEM_AUDIT_ACE_TYPE:
1013987da915Sopenharmony_ci			ace_type = "audit";
1014987da915Sopenharmony_ci			break;
1015987da915Sopenharmony_ci		default:
1016987da915Sopenharmony_ci			ace_type = "unknown";
1017987da915Sopenharmony_ci			break;
1018987da915Sopenharmony_ci		}
1019987da915Sopenharmony_ci
1020987da915Sopenharmony_ci		printf("%sACE:\t\t type:%s  flags:0x%x  access:0x%x\n", prefix,
1021987da915Sopenharmony_ci			ace_type, (unsigned int)ace->flags,
1022987da915Sopenharmony_ci			(unsigned int)le32_to_cpu(ace->mask));
1023987da915Sopenharmony_ci		/* get a SID string */
1024987da915Sopenharmony_ci		sid = ntfs_sid_to_mbs(&ace->sid, NULL, 0);
1025987da915Sopenharmony_ci		printf("%s\t\t SID: %s\n", prefix, sid);
1026987da915Sopenharmony_ci		free(sid);
1027987da915Sopenharmony_ci
1028987da915Sopenharmony_ci		/* proceed to next ACE */
1029987da915Sopenharmony_ci		ace = (ACCESS_ALLOWED_ACE *)(((char *)ace) +
1030987da915Sopenharmony_ci				le16_to_cpu(ace->size));
1031987da915Sopenharmony_ci	}
1032987da915Sopenharmony_ci}
1033987da915Sopenharmony_ci
1034987da915Sopenharmony_ci
1035987da915Sopenharmony_cistatic void ntfs_dump_security_descriptor(SECURITY_DESCRIPTOR_ATTR *sec_desc,
1036987da915Sopenharmony_ci					  const char *indent)
1037987da915Sopenharmony_ci{
1038987da915Sopenharmony_ci	char *sid;
1039987da915Sopenharmony_ci
1040987da915Sopenharmony_ci	printf("%s\tRevision:\t\t %u\n", indent, sec_desc->revision);
1041987da915Sopenharmony_ci
1042987da915Sopenharmony_ci	/* TODO: parse the flags */
1043987da915Sopenharmony_ci	printf("%s\tControl:\t\t 0x%04x\n", indent,
1044987da915Sopenharmony_ci			le16_to_cpu(sec_desc->control));
1045987da915Sopenharmony_ci
1046987da915Sopenharmony_ci	if (~sec_desc->control & SE_SELF_RELATIVE) {
1047987da915Sopenharmony_ci		SECURITY_DESCRIPTOR *sd = (SECURITY_DESCRIPTOR *)sec_desc;
1048987da915Sopenharmony_ci
1049987da915Sopenharmony_ci		printf("%s\tOwner SID pointer:\t %p\n", indent, sd->owner);
1050987da915Sopenharmony_ci		printf("%s\tGroup SID pointer:\t %p\n", indent, sd->group);
1051987da915Sopenharmony_ci		printf("%s\tSACL pointer:\t\t %p\n", indent, sd->sacl);
1052987da915Sopenharmony_ci		printf("%s\tDACL pointer:\t\t %p\n", indent, sd->dacl);
1053987da915Sopenharmony_ci
1054987da915Sopenharmony_ci		return;
1055987da915Sopenharmony_ci	}
1056987da915Sopenharmony_ci
1057987da915Sopenharmony_ci	if (sec_desc->owner) {
1058987da915Sopenharmony_ci		sid = ntfs_sid_to_mbs((SID *)((char *)sec_desc +
1059987da915Sopenharmony_ci			le32_to_cpu(sec_desc->owner)), NULL, 0);
1060987da915Sopenharmony_ci		printf("%s\tOwner SID:\t\t %s\n", indent, sid);
1061987da915Sopenharmony_ci		free(sid);
1062987da915Sopenharmony_ci	} else
1063987da915Sopenharmony_ci		printf("%s\tOwner SID:\t\t missing\n", indent);
1064987da915Sopenharmony_ci
1065987da915Sopenharmony_ci	if (sec_desc->group) {
1066987da915Sopenharmony_ci		sid = ntfs_sid_to_mbs((SID *)((char *)sec_desc +
1067987da915Sopenharmony_ci			le32_to_cpu(sec_desc->group)), NULL, 0);
1068987da915Sopenharmony_ci		printf("%s\tGroup SID:\t\t %s\n", indent, sid);
1069987da915Sopenharmony_ci		free(sid);
1070987da915Sopenharmony_ci	} else
1071987da915Sopenharmony_ci		printf("%s\tGroup SID:\t\t missing\n", indent);
1072987da915Sopenharmony_ci
1073987da915Sopenharmony_ci	printf("%s\tSystem ACL:\t\t ", indent);
1074987da915Sopenharmony_ci	if (sec_desc->control & SE_SACL_PRESENT) {
1075987da915Sopenharmony_ci		if (sec_desc->control & SE_SACL_DEFAULTED) {
1076987da915Sopenharmony_ci			printf("defaulted");
1077987da915Sopenharmony_ci		}
1078987da915Sopenharmony_ci		printf("\n");
1079987da915Sopenharmony_ci		ntfs_dump_acl(indent ? "\t\t\t" : "\t\t",
1080987da915Sopenharmony_ci			      (ACL *)((char *)sec_desc +
1081987da915Sopenharmony_ci				      le32_to_cpu(sec_desc->sacl)));
1082987da915Sopenharmony_ci	} else {
1083987da915Sopenharmony_ci		printf("missing\n");
1084987da915Sopenharmony_ci	}
1085987da915Sopenharmony_ci
1086987da915Sopenharmony_ci	printf("%s\tDiscretionary ACL:\t ", indent);
1087987da915Sopenharmony_ci	if (sec_desc->control & SE_DACL_PRESENT) {
1088987da915Sopenharmony_ci		if (sec_desc->control & SE_SACL_DEFAULTED) {
1089987da915Sopenharmony_ci			printf("defaulted");
1090987da915Sopenharmony_ci		}
1091987da915Sopenharmony_ci		printf("\n");
1092987da915Sopenharmony_ci		ntfs_dump_acl(indent ? "\t\t\t" : "\t\t",
1093987da915Sopenharmony_ci			      (ACL *)((char *)sec_desc +
1094987da915Sopenharmony_ci				      le32_to_cpu(sec_desc->dacl)));
1095987da915Sopenharmony_ci	} else {
1096987da915Sopenharmony_ci		printf("missing\n");
1097987da915Sopenharmony_ci	}
1098987da915Sopenharmony_ci}
1099987da915Sopenharmony_ci
1100987da915Sopenharmony_ci/**
1101987da915Sopenharmony_ci * ntfs_dump_security_descriptor()
1102987da915Sopenharmony_ci *
1103987da915Sopenharmony_ci * dump the security information about the file
1104987da915Sopenharmony_ci */
1105987da915Sopenharmony_cistatic void ntfs_dump_attr_security_descriptor(ATTR_RECORD *attr, ntfs_volume *vol)
1106987da915Sopenharmony_ci{
1107987da915Sopenharmony_ci	SECURITY_DESCRIPTOR_ATTR *sec_desc_attr;
1108987da915Sopenharmony_ci
1109987da915Sopenharmony_ci	if (attr->non_resident) {
1110987da915Sopenharmony_ci		/* FIXME: We don't handle fragmented mapping pairs case. */
1111987da915Sopenharmony_ci		runlist *rl = ntfs_mapping_pairs_decompress(vol, attr, NULL);
1112987da915Sopenharmony_ci		if (rl) {
1113987da915Sopenharmony_ci			s64 data_size, bytes_read;
1114987da915Sopenharmony_ci
1115987da915Sopenharmony_ci			data_size = sle64_to_cpu(attr->data_size);
1116987da915Sopenharmony_ci			sec_desc_attr = ntfs_malloc(data_size);
1117987da915Sopenharmony_ci			if (!sec_desc_attr) {
1118987da915Sopenharmony_ci				free(rl);
1119987da915Sopenharmony_ci				return;
1120987da915Sopenharmony_ci			}
1121987da915Sopenharmony_ci			bytes_read = ntfs_rl_pread(vol, rl, 0,
1122987da915Sopenharmony_ci						data_size, sec_desc_attr);
1123987da915Sopenharmony_ci			if (bytes_read != data_size) {
1124987da915Sopenharmony_ci				ntfs_log_error("ntfsinfo error: could not "
1125987da915Sopenharmony_ci						"read security descriptor\n");
1126987da915Sopenharmony_ci				free(rl);
1127987da915Sopenharmony_ci				free(sec_desc_attr);
1128987da915Sopenharmony_ci				return;
1129987da915Sopenharmony_ci			}
1130987da915Sopenharmony_ci			free(rl);
1131987da915Sopenharmony_ci		} else {
1132987da915Sopenharmony_ci			ntfs_log_error("ntfsinfo error: could not "
1133987da915Sopenharmony_ci						"decompress runlist\n");
1134987da915Sopenharmony_ci			return;
1135987da915Sopenharmony_ci		}
1136987da915Sopenharmony_ci	} else {
1137987da915Sopenharmony_ci		sec_desc_attr = (SECURITY_DESCRIPTOR_ATTR *)((u8*)attr +
1138987da915Sopenharmony_ci				le16_to_cpu(attr->value_offset));
1139987da915Sopenharmony_ci	}
1140987da915Sopenharmony_ci
1141987da915Sopenharmony_ci	ntfs_dump_security_descriptor(sec_desc_attr, "");
1142987da915Sopenharmony_ci
1143987da915Sopenharmony_ci	if (attr->non_resident)
1144987da915Sopenharmony_ci		free(sec_desc_attr);
1145987da915Sopenharmony_ci}
1146987da915Sopenharmony_ci
1147987da915Sopenharmony_ci/**
1148987da915Sopenharmony_ci * ntfs_dump_volume_name()
1149987da915Sopenharmony_ci *
1150987da915Sopenharmony_ci * dump the name of the volume the inode belongs to
1151987da915Sopenharmony_ci */
1152987da915Sopenharmony_cistatic void ntfs_dump_attr_volume_name(ATTR_RECORD *attr)
1153987da915Sopenharmony_ci{
1154987da915Sopenharmony_ci	ntfschar *ucs_vol_name = NULL;
1155987da915Sopenharmony_ci
1156987da915Sopenharmony_ci	if (le32_to_cpu(attr->value_length) > 0) {
1157987da915Sopenharmony_ci		char *mbs_vol_name = NULL;
1158987da915Sopenharmony_ci		int mbs_vol_name_size;
1159987da915Sopenharmony_ci		/* calculate volume name position */
1160987da915Sopenharmony_ci		ucs_vol_name = (ntfschar*)((u8*)attr +
1161987da915Sopenharmony_ci				le16_to_cpu(attr->value_offset));
1162987da915Sopenharmony_ci		/* convert the name to current locale multibyte sequence */
1163987da915Sopenharmony_ci		mbs_vol_name_size = ntfs_ucstombs(ucs_vol_name,
1164987da915Sopenharmony_ci				le32_to_cpu(attr->value_length) /
1165987da915Sopenharmony_ci				sizeof(ntfschar), &mbs_vol_name, 0);
1166987da915Sopenharmony_ci
1167987da915Sopenharmony_ci		if (mbs_vol_name_size>0) {
1168987da915Sopenharmony_ci			/* output the converted name. */
1169987da915Sopenharmony_ci			printf("\tVolume Name:\t\t '%s'\n", mbs_vol_name);
1170987da915Sopenharmony_ci			free(mbs_vol_name);
1171987da915Sopenharmony_ci		} else
1172987da915Sopenharmony_ci			ntfs_log_perror("ntfsinfo error: could not parse "
1173987da915Sopenharmony_ci					"volume name");
1174987da915Sopenharmony_ci	} else
1175987da915Sopenharmony_ci		printf("\tVolume Name:\t\t unnamed\n");
1176987da915Sopenharmony_ci}
1177987da915Sopenharmony_ci
1178987da915Sopenharmony_ci/**
1179987da915Sopenharmony_ci * ntfs_dump_volume_information()
1180987da915Sopenharmony_ci *
1181987da915Sopenharmony_ci * dump the information for the volume the inode belongs to
1182987da915Sopenharmony_ci *
1183987da915Sopenharmony_ci */
1184987da915Sopenharmony_cistatic void ntfs_dump_attr_volume_information(ATTR_RECORD *attr)
1185987da915Sopenharmony_ci{
1186987da915Sopenharmony_ci	VOLUME_INFORMATION *vol_information = NULL;
1187987da915Sopenharmony_ci
1188987da915Sopenharmony_ci	vol_information = (VOLUME_INFORMATION*)((char *)attr+
1189987da915Sopenharmony_ci		le16_to_cpu(attr->value_offset));
1190987da915Sopenharmony_ci
1191987da915Sopenharmony_ci	printf("\tVolume Version:\t\t %d.%d\n", vol_information->major_ver,
1192987da915Sopenharmony_ci		vol_information->minor_ver);
1193987da915Sopenharmony_ci	printf("\tVolume Flags:\t\t ");
1194987da915Sopenharmony_ci	if (vol_information->flags & VOLUME_IS_DIRTY)
1195987da915Sopenharmony_ci		printf("DIRTY ");
1196987da915Sopenharmony_ci	if (vol_information->flags & VOLUME_RESIZE_LOG_FILE)
1197987da915Sopenharmony_ci		printf("RESIZE_LOG ");
1198987da915Sopenharmony_ci	if (vol_information->flags & VOLUME_UPGRADE_ON_MOUNT)
1199987da915Sopenharmony_ci		printf("UPG_ON_MOUNT ");
1200987da915Sopenharmony_ci	if (vol_information->flags & VOLUME_MOUNTED_ON_NT4)
1201987da915Sopenharmony_ci		printf("MOUNTED_NT4 ");
1202987da915Sopenharmony_ci	if (vol_information->flags & VOLUME_DELETE_USN_UNDERWAY)
1203987da915Sopenharmony_ci		printf("DEL_USN ");
1204987da915Sopenharmony_ci	if (vol_information->flags & VOLUME_REPAIR_OBJECT_ID)
1205987da915Sopenharmony_ci		printf("REPAIR_OBJID ");
1206987da915Sopenharmony_ci	if (vol_information->flags & VOLUME_CHKDSK_UNDERWAY)
1207987da915Sopenharmony_ci		printf("CHKDSK_UNDERWAY ");
1208987da915Sopenharmony_ci	if (vol_information->flags & VOLUME_MODIFIED_BY_CHKDSK)
1209987da915Sopenharmony_ci		printf("MOD_BY_CHKDSK ");
1210987da915Sopenharmony_ci	if (vol_information->flags & VOLUME_FLAGS_MASK) {
1211987da915Sopenharmony_ci		printf("(0x%04x)\n",
1212987da915Sopenharmony_ci				(unsigned)le16_to_cpu(vol_information->flags));
1213987da915Sopenharmony_ci	} else
1214987da915Sopenharmony_ci		printf("none set (0x0000)\n");
1215987da915Sopenharmony_ci	if (vol_information->flags & (~VOLUME_FLAGS_MASK))
1216987da915Sopenharmony_ci		printf("\t\t\t\t Unknown Flags: 0x%04x\n",
1217987da915Sopenharmony_ci				le16_to_cpu(vol_information->flags &
1218987da915Sopenharmony_ci					(~VOLUME_FLAGS_MASK)));
1219987da915Sopenharmony_ci}
1220987da915Sopenharmony_ci
1221987da915Sopenharmony_cistatic ntfschar NTFS_DATA_SDS[5] = { const_cpu_to_le16('$'),
1222987da915Sopenharmony_ci	const_cpu_to_le16('S'), const_cpu_to_le16('D'),
1223987da915Sopenharmony_ci	const_cpu_to_le16('S'), const_cpu_to_le16('\0') };
1224987da915Sopenharmony_ci
1225987da915Sopenharmony_cistatic void ntfs_dump_sds_entry(SECURITY_DESCRIPTOR_HEADER *sds)
1226987da915Sopenharmony_ci{
1227987da915Sopenharmony_ci	SECURITY_DESCRIPTOR_RELATIVE *sd;
1228987da915Sopenharmony_ci
1229987da915Sopenharmony_ci	ntfs_log_verbose("\n");
1230987da915Sopenharmony_ci	ntfs_log_verbose("\t\tHash:\t\t\t 0x%08x\n",
1231987da915Sopenharmony_ci			(unsigned)le32_to_cpu(sds->hash));
1232987da915Sopenharmony_ci	ntfs_log_verbose("\t\tSecurity id:\t\t %u (0x%x)\n",
1233987da915Sopenharmony_ci			(unsigned)le32_to_cpu(sds->security_id),
1234987da915Sopenharmony_ci			(unsigned)le32_to_cpu(sds->security_id));
1235987da915Sopenharmony_ci	ntfs_log_verbose("\t\tOffset:\t\t\t %llu (0x%llx)\n",
1236987da915Sopenharmony_ci			(unsigned long long)le64_to_cpu(sds->offset),
1237987da915Sopenharmony_ci			(unsigned long long)le64_to_cpu(sds->offset));
1238987da915Sopenharmony_ci	ntfs_log_verbose("\t\tLength:\t\t\t %u (0x%x)\n",
1239987da915Sopenharmony_ci			(unsigned)le32_to_cpu(sds->length),
1240987da915Sopenharmony_ci			(unsigned)le32_to_cpu(sds->length));
1241987da915Sopenharmony_ci
1242987da915Sopenharmony_ci	sd = (SECURITY_DESCRIPTOR_RELATIVE *)((char *)sds +
1243987da915Sopenharmony_ci		sizeof(SECURITY_DESCRIPTOR_HEADER));
1244987da915Sopenharmony_ci
1245987da915Sopenharmony_ci	ntfs_dump_security_descriptor(sd, "\t");
1246987da915Sopenharmony_ci}
1247987da915Sopenharmony_ci
1248987da915Sopenharmony_cistatic void ntfs_dump_sds(ATTR_RECORD *attr, ntfs_inode *ni)
1249987da915Sopenharmony_ci{
1250987da915Sopenharmony_ci	SECURITY_DESCRIPTOR_HEADER *sds, *sd;
1251987da915Sopenharmony_ci	ntfschar *name;
1252987da915Sopenharmony_ci	int name_len;
1253987da915Sopenharmony_ci	s64 data_size;
1254987da915Sopenharmony_ci	u64 inode;
1255987da915Sopenharmony_ci
1256987da915Sopenharmony_ci	inode = ni->mft_no;
1257987da915Sopenharmony_ci	if (ni->nr_extents < 0)
1258987da915Sopenharmony_ci		inode = ni->base_ni->mft_no;
1259987da915Sopenharmony_ci	if (FILE_Secure != inode)
1260987da915Sopenharmony_ci		return;
1261987da915Sopenharmony_ci
1262987da915Sopenharmony_ci	name_len = attr->name_length;
1263987da915Sopenharmony_ci	if (!name_len)
1264987da915Sopenharmony_ci		return;
1265987da915Sopenharmony_ci
1266987da915Sopenharmony_ci	name = (ntfschar *)((u8 *)attr + le16_to_cpu(attr->name_offset));
1267987da915Sopenharmony_ci	if (!ntfs_names_are_equal(NTFS_DATA_SDS, sizeof(NTFS_DATA_SDS) / 2 - 1,
1268987da915Sopenharmony_ci				  name, name_len, CASE_SENSITIVE, NULL, 0))
1269987da915Sopenharmony_ci		return;
1270987da915Sopenharmony_ci
1271987da915Sopenharmony_ci	sd = sds = ntfs_attr_readall(ni, AT_DATA, name, name_len, &data_size);
1272987da915Sopenharmony_ci	if (!sd) {
1273987da915Sopenharmony_ci		ntfs_log_perror("Failed to read $SDS attribute");
1274987da915Sopenharmony_ci		return;
1275987da915Sopenharmony_ci	}
1276987da915Sopenharmony_ci	/*
1277987da915Sopenharmony_ci	 * FIXME: The right way is based on the indexes, so we couldn't
1278987da915Sopenharmony_ci	 * miss real entries. For now, dump until it makes sense.
1279987da915Sopenharmony_ci	 */
1280987da915Sopenharmony_ci	while (sd->length && sd->hash &&
1281987da915Sopenharmony_ci	       le64_to_cpu(sd->offset) < (u64)data_size &&
1282987da915Sopenharmony_ci	       le32_to_cpu(sd->length) < (u64)data_size &&
1283987da915Sopenharmony_ci	       le64_to_cpu(sd->offset) +
1284987da915Sopenharmony_ci			le32_to_cpu(sd->length) < (u64)data_size) {
1285987da915Sopenharmony_ci		ntfs_dump_sds_entry(sd);
1286987da915Sopenharmony_ci		sd = (SECURITY_DESCRIPTOR_HEADER *)((char*)sd +
1287987da915Sopenharmony_ci				((le32_to_cpu(sd->length) + 15) & ~15));
1288987da915Sopenharmony_ci	}
1289987da915Sopenharmony_ci	free(sds);
1290987da915Sopenharmony_ci}
1291987da915Sopenharmony_ci
1292987da915Sopenharmony_cistatic const char *get_attribute_type_name(le32 type)
1293987da915Sopenharmony_ci{
1294987da915Sopenharmony_ci	switch (type) {
1295987da915Sopenharmony_ci	case AT_UNUSED:			return "$UNUSED";
1296987da915Sopenharmony_ci	case AT_STANDARD_INFORMATION:   return "$STANDARD_INFORMATION";
1297987da915Sopenharmony_ci	case AT_ATTRIBUTE_LIST:         return "$ATTRIBUTE_LIST";
1298987da915Sopenharmony_ci	case AT_FILE_NAME:              return "$FILE_NAME";
1299987da915Sopenharmony_ci	case AT_OBJECT_ID:              return "$OBJECT_ID";
1300987da915Sopenharmony_ci	case AT_SECURITY_DESCRIPTOR:    return "$SECURITY_DESCRIPTOR";
1301987da915Sopenharmony_ci	case AT_VOLUME_NAME:            return "$VOLUME_NAME";
1302987da915Sopenharmony_ci	case AT_VOLUME_INFORMATION:     return "$VOLUME_INFORMATION";
1303987da915Sopenharmony_ci	case AT_DATA:                   return "$DATA";
1304987da915Sopenharmony_ci	case AT_INDEX_ROOT:             return "$INDEX_ROOT";
1305987da915Sopenharmony_ci	case AT_INDEX_ALLOCATION:       return "$INDEX_ALLOCATION";
1306987da915Sopenharmony_ci	case AT_BITMAP:                 return "$BITMAP";
1307987da915Sopenharmony_ci	case AT_REPARSE_POINT:          return "$REPARSE_POINT";
1308987da915Sopenharmony_ci	case AT_EA_INFORMATION:         return "$EA_INFORMATION";
1309987da915Sopenharmony_ci	case AT_EA:                     return "$EA";
1310987da915Sopenharmony_ci	case AT_PROPERTY_SET:           return "$PROPERTY_SET";
1311987da915Sopenharmony_ci	case AT_LOGGED_UTILITY_STREAM:  return "$LOGGED_UTILITY_STREAM";
1312987da915Sopenharmony_ci	case AT_END:                    return "$END";
1313987da915Sopenharmony_ci	}
1314987da915Sopenharmony_ci
1315987da915Sopenharmony_ci	return "$UNKNOWN";
1316987da915Sopenharmony_ci}
1317987da915Sopenharmony_ci
1318987da915Sopenharmony_cistatic const char * ntfs_dump_lcn(LCN lcn)
1319987da915Sopenharmony_ci{
1320987da915Sopenharmony_ci	switch (lcn) {
1321987da915Sopenharmony_ci		case LCN_HOLE:
1322987da915Sopenharmony_ci			return "<HOLE>\t";
1323987da915Sopenharmony_ci		case LCN_RL_NOT_MAPPED:
1324987da915Sopenharmony_ci			return "<RL_NOT_MAPPED>";
1325987da915Sopenharmony_ci		case LCN_ENOENT:
1326987da915Sopenharmony_ci			return "<ENOENT>\t";
1327987da915Sopenharmony_ci		case LCN_EINVAL:
1328987da915Sopenharmony_ci			return "<EINVAL>\t";
1329987da915Sopenharmony_ci		case LCN_EIO:
1330987da915Sopenharmony_ci			return "<EIO>\t";
1331987da915Sopenharmony_ci		default:
1332987da915Sopenharmony_ci			ntfs_log_error("Invalid LCN value %llx passed to "
1333987da915Sopenharmony_ci					"ntfs_dump_lcn().\n", (long long)lcn);
1334987da915Sopenharmony_ci			return "???\t";
1335987da915Sopenharmony_ci	}
1336987da915Sopenharmony_ci}
1337987da915Sopenharmony_ci
1338987da915Sopenharmony_cistatic void ntfs_dump_attribute_header(ntfs_attr_search_ctx *ctx,
1339987da915Sopenharmony_ci		ntfs_volume *vol, struct RUNCOUNT *runcount)
1340987da915Sopenharmony_ci{
1341987da915Sopenharmony_ci	ATTR_RECORD *a = ctx->attr;
1342987da915Sopenharmony_ci
1343987da915Sopenharmony_ci	printf("Dumping attribute %s (0x%x) from mft record %lld (0x%llx)\n",
1344987da915Sopenharmony_ci			get_attribute_type_name(a->type),
1345987da915Sopenharmony_ci			(unsigned)le32_to_cpu(a->type),
1346987da915Sopenharmony_ci			(unsigned long long)ctx->ntfs_ino->mft_no,
1347987da915Sopenharmony_ci			(unsigned long long)ctx->ntfs_ino->mft_no);
1348987da915Sopenharmony_ci
1349987da915Sopenharmony_ci	ntfs_log_verbose("\tAttribute length:\t %u (0x%x)\n",
1350987da915Sopenharmony_ci			(unsigned)le32_to_cpu(a->length),
1351987da915Sopenharmony_ci			(unsigned)le32_to_cpu(a->length));
1352987da915Sopenharmony_ci	printf("\tResident: \t\t %s\n", a->non_resident ? "No" : "Yes");
1353987da915Sopenharmony_ci	ntfs_log_verbose("\tName length:\t\t %u (0x%x)\n",
1354987da915Sopenharmony_ci			(unsigned)a->name_length, (unsigned)a->name_length);
1355987da915Sopenharmony_ci	ntfs_log_verbose("\tName offset:\t\t %u (0x%x)\n",
1356987da915Sopenharmony_ci			(unsigned)le16_to_cpu(a->name_offset),
1357987da915Sopenharmony_ci			(unsigned)le16_to_cpu(a->name_offset));
1358987da915Sopenharmony_ci
1359987da915Sopenharmony_ci	/* Dump the attribute (stream) name */
1360987da915Sopenharmony_ci	if (a->name_length) {
1361987da915Sopenharmony_ci		char *attribute_name = NULL;
1362987da915Sopenharmony_ci
1363987da915Sopenharmony_ci		attribute_name = ntfs_attr_get_name_mbs(a);
1364987da915Sopenharmony_ci		if (attribute_name) {
1365987da915Sopenharmony_ci			printf("\tAttribute name:\t\t '%s'\n", attribute_name);
1366987da915Sopenharmony_ci			free(attribute_name);
1367987da915Sopenharmony_ci		} else
1368987da915Sopenharmony_ci			ntfs_log_perror("Error: couldn't parse attribute name");
1369987da915Sopenharmony_ci	}
1370987da915Sopenharmony_ci
1371987da915Sopenharmony_ci	/* TODO: parse the flags */
1372987da915Sopenharmony_ci	printf("\tAttribute flags:\t 0x%04x\n",
1373987da915Sopenharmony_ci			(unsigned)le16_to_cpu(a->flags));
1374987da915Sopenharmony_ci	printf("\tAttribute instance:\t %u (0x%x)\n",
1375987da915Sopenharmony_ci			(unsigned)le16_to_cpu(a->instance),
1376987da915Sopenharmony_ci			(unsigned)le16_to_cpu(a->instance));
1377987da915Sopenharmony_ci
1378987da915Sopenharmony_ci	/* Resident attribute */
1379987da915Sopenharmony_ci	if (!a->non_resident) {
1380987da915Sopenharmony_ci		printf("\tData size:\t\t %u (0x%x)\n",
1381987da915Sopenharmony_ci				(unsigned)le32_to_cpu(a->value_length),
1382987da915Sopenharmony_ci				(unsigned)le32_to_cpu(a->value_length));
1383987da915Sopenharmony_ci		ntfs_log_verbose("\tData offset:\t\t %u (0x%x)\n",
1384987da915Sopenharmony_ci				(unsigned)le16_to_cpu(a->value_offset),
1385987da915Sopenharmony_ci				(unsigned)le16_to_cpu(a->value_offset));
1386987da915Sopenharmony_ci		/* TODO: parse the flags */
1387987da915Sopenharmony_ci		printf("\tResident flags:\t\t 0x%02x\n",
1388987da915Sopenharmony_ci				(unsigned)a->resident_flags);
1389987da915Sopenharmony_ci		ntfs_log_verbose("\tReservedR:\t\t %d (0x%x)\n",
1390987da915Sopenharmony_ci				(unsigned)a->reservedR, (unsigned)a->reservedR);
1391987da915Sopenharmony_ci		return;
1392987da915Sopenharmony_ci	}
1393987da915Sopenharmony_ci
1394987da915Sopenharmony_ci	/* Non-resident attribute */
1395987da915Sopenharmony_ci	ntfs_log_verbose("\tLowest VCN\t\t %lld (0x%llx)\n",
1396987da915Sopenharmony_ci			(long long)sle64_to_cpu(a->lowest_vcn),
1397987da915Sopenharmony_ci			(unsigned long long)sle64_to_cpu(a->lowest_vcn));
1398987da915Sopenharmony_ci	ntfs_log_verbose("\tHighest VCN:\t\t %lld (0x%llx)\n",
1399987da915Sopenharmony_ci			(long long)sle64_to_cpu(a->highest_vcn),
1400987da915Sopenharmony_ci			(unsigned long long)sle64_to_cpu(a->highest_vcn));
1401987da915Sopenharmony_ci	ntfs_log_verbose("\tMapping pairs offset:\t %u (0x%x)\n",
1402987da915Sopenharmony_ci			(unsigned)le16_to_cpu(a->mapping_pairs_offset),
1403987da915Sopenharmony_ci			(unsigned)le16_to_cpu(a->mapping_pairs_offset));
1404987da915Sopenharmony_ci	printf("\tCompression unit:\t %u (0x%x)\n",
1405987da915Sopenharmony_ci			(unsigned)a->compression_unit,
1406987da915Sopenharmony_ci			(unsigned)a->compression_unit);
1407987da915Sopenharmony_ci	/* TODO: dump the 5 reserved bytes here in verbose mode */
1408987da915Sopenharmony_ci
1409987da915Sopenharmony_ci	if (!a->lowest_vcn) {
1410987da915Sopenharmony_ci		printf("\tData size:\t\t %llu (0x%llx)\n",
1411987da915Sopenharmony_ci				(long long)sle64_to_cpu(a->data_size),
1412987da915Sopenharmony_ci				(unsigned long long)sle64_to_cpu(a->data_size));
1413987da915Sopenharmony_ci		printf("\tAllocated size:\t\t %llu (0x%llx)\n",
1414987da915Sopenharmony_ci				(long long)sle64_to_cpu(a->allocated_size),
1415987da915Sopenharmony_ci				(unsigned long long)
1416987da915Sopenharmony_ci				sle64_to_cpu(a->allocated_size));
1417987da915Sopenharmony_ci		printf("\tInitialized size:\t %llu (0x%llx)\n",
1418987da915Sopenharmony_ci				(long long)sle64_to_cpu(a->initialized_size),
1419987da915Sopenharmony_ci				(unsigned long long)
1420987da915Sopenharmony_ci				sle64_to_cpu(a->initialized_size));
1421987da915Sopenharmony_ci		if (a->compression_unit || a->flags & ATTR_IS_COMPRESSED ||
1422987da915Sopenharmony_ci				a->flags & ATTR_IS_SPARSE)
1423987da915Sopenharmony_ci			printf("\tCompressed size:\t %llu (0x%llx)\n",
1424987da915Sopenharmony_ci					(signed long long)
1425987da915Sopenharmony_ci					sle64_to_cpu(a->compressed_size),
1426987da915Sopenharmony_ci					(signed long long)
1427987da915Sopenharmony_ci					sle64_to_cpu(a->compressed_size));
1428987da915Sopenharmony_ci	}
1429987da915Sopenharmony_ci
1430987da915Sopenharmony_ci	if (opts.verbose) {
1431987da915Sopenharmony_ci		runlist *rl;
1432987da915Sopenharmony_ci
1433987da915Sopenharmony_ci		rl = ntfs_mapping_pairs_decompress(vol, a, NULL);
1434987da915Sopenharmony_ci		if (rl) {
1435987da915Sopenharmony_ci			runlist *rlc = rl;
1436987da915Sopenharmony_ci			LCN next_lcn;
1437987da915Sopenharmony_ci
1438987da915Sopenharmony_ci			next_lcn = LCN_HOLE;
1439987da915Sopenharmony_ci			// TODO: Switch this to properly aligned hex...
1440987da915Sopenharmony_ci			printf("\tRunlist:\tVCN\t\tLCN\t\tLength\n");
1441987da915Sopenharmony_ci			runcount->fragments++;
1442987da915Sopenharmony_ci			while (rlc->length) {
1443987da915Sopenharmony_ci				runcount->runs++;
1444987da915Sopenharmony_ci				if (rlc->lcn >= 0) {
1445987da915Sopenharmony_ci					printf("\t\t\t0x%llx\t\t0x%llx\t\t"
1446987da915Sopenharmony_ci							"0x%llx\n",
1447987da915Sopenharmony_ci							(long long)rlc->vcn,
1448987da915Sopenharmony_ci							(long long)rlc->lcn,
1449987da915Sopenharmony_ci							(long long)rlc->length);
1450987da915Sopenharmony_ci					if ((next_lcn >= 0)
1451987da915Sopenharmony_ci					    && (rlc->lcn != next_lcn))
1452987da915Sopenharmony_ci						runcount->fragments++;
1453987da915Sopenharmony_ci					next_lcn = rlc->lcn + rlc->length;
1454987da915Sopenharmony_ci				} else
1455987da915Sopenharmony_ci					printf("\t\t\t0x%llx\t\t%s\t"
1456987da915Sopenharmony_ci							"0x%llx\n",
1457987da915Sopenharmony_ci							(long long)rlc->vcn,
1458987da915Sopenharmony_ci							ntfs_dump_lcn(rlc->lcn),
1459987da915Sopenharmony_ci							(long long)rlc->length);
1460987da915Sopenharmony_ci				rlc++;
1461987da915Sopenharmony_ci			}
1462987da915Sopenharmony_ci			free(rl);
1463987da915Sopenharmony_ci		} else
1464987da915Sopenharmony_ci			ntfs_log_error("Error: couldn't decompress runlist\n");
1465987da915Sopenharmony_ci	}
1466987da915Sopenharmony_ci}
1467987da915Sopenharmony_ci
1468987da915Sopenharmony_ci/**
1469987da915Sopenharmony_ci * ntfs_dump_data_attr()
1470987da915Sopenharmony_ci *
1471987da915Sopenharmony_ci * dump some info about the data attribute if it's metadata
1472987da915Sopenharmony_ci */
1473987da915Sopenharmony_cistatic void ntfs_dump_attr_data(ATTR_RECORD *attr, ntfs_inode *ni)
1474987da915Sopenharmony_ci{
1475987da915Sopenharmony_ci	if (opts.verbose)
1476987da915Sopenharmony_ci		ntfs_dump_sds(attr, ni);
1477987da915Sopenharmony_ci}
1478987da915Sopenharmony_ci
1479987da915Sopenharmony_citypedef enum {
1480987da915Sopenharmony_ci	INDEX_ATTR_UNKNOWN,
1481987da915Sopenharmony_ci	INDEX_ATTR_DIRECTORY_I30,
1482987da915Sopenharmony_ci	INDEX_ATTR_SECURE_SII,
1483987da915Sopenharmony_ci	INDEX_ATTR_SECURE_SDH,
1484987da915Sopenharmony_ci	INDEX_ATTR_OBJID_O,
1485987da915Sopenharmony_ci	INDEX_ATTR_REPARSE_R,
1486987da915Sopenharmony_ci	INDEX_ATTR_QUOTA_O,
1487987da915Sopenharmony_ci	INDEX_ATTR_QUOTA_Q,
1488987da915Sopenharmony_ci} INDEX_ATTR_TYPE;
1489987da915Sopenharmony_ci
1490987da915Sopenharmony_cistatic void ntfs_dump_index_key(INDEX_ENTRY *entry, INDEX_ATTR_TYPE type)
1491987da915Sopenharmony_ci{
1492987da915Sopenharmony_ci	char *sid;
1493987da915Sopenharmony_ci	char printable_GUID[37];
1494987da915Sopenharmony_ci	le32 tag;
1495987da915Sopenharmony_ci
1496987da915Sopenharmony_ci	switch (type) {
1497987da915Sopenharmony_ci	case INDEX_ATTR_SECURE_SII:
1498987da915Sopenharmony_ci		ntfs_log_verbose("\t\tKey security id:\t %u (0x%x)\n",
1499987da915Sopenharmony_ci				(unsigned)
1500987da915Sopenharmony_ci				le32_to_cpu(entry->key.sii.security_id),
1501987da915Sopenharmony_ci				(unsigned)
1502987da915Sopenharmony_ci				le32_to_cpu(entry->key.sii.security_id));
1503987da915Sopenharmony_ci		break;
1504987da915Sopenharmony_ci	case INDEX_ATTR_SECURE_SDH:
1505987da915Sopenharmony_ci		ntfs_log_verbose("\t\tKey hash:\t\t 0x%08x\n",
1506987da915Sopenharmony_ci				(unsigned)le32_to_cpu(entry->key.sdh.hash));
1507987da915Sopenharmony_ci		ntfs_log_verbose("\t\tKey security id:\t %u (0x%x)\n",
1508987da915Sopenharmony_ci				(unsigned)
1509987da915Sopenharmony_ci				le32_to_cpu(entry->key.sdh.security_id),
1510987da915Sopenharmony_ci				(unsigned)
1511987da915Sopenharmony_ci				le32_to_cpu(entry->key.sdh.security_id));
1512987da915Sopenharmony_ci		break;
1513987da915Sopenharmony_ci	case INDEX_ATTR_OBJID_O:
1514987da915Sopenharmony_ci		ntfs_guid_to_mbs(&entry->key.object_id, printable_GUID);
1515987da915Sopenharmony_ci		ntfs_log_verbose("\t\tKey GUID:\t\t %s\n", printable_GUID);
1516987da915Sopenharmony_ci		break;
1517987da915Sopenharmony_ci	case INDEX_ATTR_REPARSE_R:
1518987da915Sopenharmony_ci		tag = entry->key.reparse.reparse_tag;
1519987da915Sopenharmony_ci		ntfs_log_verbose("\t\tKey reparse tag:\t 0x%08lx%s\n",
1520987da915Sopenharmony_ci				(long)le32_to_cpu(tag),
1521987da915Sopenharmony_ci				reparse_type_name(tag));
1522987da915Sopenharmony_ci		ntfs_log_verbose("\t\tKey file id:\t\t %llu (0x%llx)\n",
1523987da915Sopenharmony_ci				(unsigned long long)
1524987da915Sopenharmony_ci				le64_to_cpu(entry->key.reparse.file_id),
1525987da915Sopenharmony_ci				(unsigned long long)
1526987da915Sopenharmony_ci				le64_to_cpu(entry->key.reparse.file_id));
1527987da915Sopenharmony_ci		break;
1528987da915Sopenharmony_ci	case INDEX_ATTR_QUOTA_O:
1529987da915Sopenharmony_ci		sid = ntfs_sid_to_mbs(&entry->key.sid, NULL, 0);
1530987da915Sopenharmony_ci		ntfs_log_verbose("\t\tKey SID:\t\t %s\n", sid);
1531987da915Sopenharmony_ci		free(sid);
1532987da915Sopenharmony_ci		break;
1533987da915Sopenharmony_ci	case INDEX_ATTR_QUOTA_Q:
1534987da915Sopenharmony_ci		ntfs_log_verbose("\t\tKey owner id:\t\t %u (0x%x)\n",
1535987da915Sopenharmony_ci				(unsigned)le32_to_cpu(entry->key.owner_id),
1536987da915Sopenharmony_ci				(unsigned)le32_to_cpu(entry->key.owner_id));
1537987da915Sopenharmony_ci		break;
1538987da915Sopenharmony_ci	default:
1539987da915Sopenharmony_ci		ntfs_log_verbose("\t\tIndex attr type is UNKNOWN: \t 0x%08x\n",
1540987da915Sopenharmony_ci				(unsigned)type);
1541987da915Sopenharmony_ci		break;
1542987da915Sopenharmony_ci	}
1543987da915Sopenharmony_ci}
1544987da915Sopenharmony_ci
1545987da915Sopenharmony_citypedef union {
1546987da915Sopenharmony_ci	SII_INDEX_DATA sii;		/* $SII index data in $Secure */
1547987da915Sopenharmony_ci	SDH_INDEX_DATA sdh;		/* $SDH index data in $Secure */
1548987da915Sopenharmony_ci	QUOTA_O_INDEX_DATA quota_o;	/* $O index data in $Quota    */
1549987da915Sopenharmony_ci	QUOTA_CONTROL_ENTRY quota_q;	/* $Q index data in $Quota    */
1550987da915Sopenharmony_ci} __attribute__((__packed__)) INDEX_ENTRY_DATA;
1551987da915Sopenharmony_ci
1552987da915Sopenharmony_cistatic void ntfs_dump_index_data(INDEX_ENTRY *entry, INDEX_ATTR_TYPE type)
1553987da915Sopenharmony_ci{
1554987da915Sopenharmony_ci	INDEX_ENTRY_DATA *data;
1555987da915Sopenharmony_ci
1556987da915Sopenharmony_ci	data = (INDEX_ENTRY_DATA *)((u8 *)entry +
1557987da915Sopenharmony_ci			le16_to_cpu(entry->data_offset));
1558987da915Sopenharmony_ci
1559987da915Sopenharmony_ci	switch (type) {
1560987da915Sopenharmony_ci	case INDEX_ATTR_SECURE_SII:
1561987da915Sopenharmony_ci		ntfs_log_verbose("\t\tHash:\t\t\t 0x%08x\n",
1562987da915Sopenharmony_ci				(unsigned)le32_to_cpu(data->sii.hash));
1563987da915Sopenharmony_ci		ntfs_log_verbose("\t\tSecurity id:\t\t %u (0x%x)\n",
1564987da915Sopenharmony_ci				(unsigned)le32_to_cpu(data->sii.security_id),
1565987da915Sopenharmony_ci				(unsigned)le32_to_cpu(data->sii.security_id));
1566987da915Sopenharmony_ci		ntfs_log_verbose("\t\tOffset in $SDS:\t\t %llu (0x%llx)\n",
1567987da915Sopenharmony_ci				(unsigned long long)
1568987da915Sopenharmony_ci				le64_to_cpu(data->sii.offset),
1569987da915Sopenharmony_ci				(unsigned long long)
1570987da915Sopenharmony_ci				le64_to_cpu(data->sii.offset));
1571987da915Sopenharmony_ci		ntfs_log_verbose("\t\tLength in $SDS:\t\t %u (0x%x)\n",
1572987da915Sopenharmony_ci				(unsigned)le32_to_cpu(data->sii.length),
1573987da915Sopenharmony_ci				(unsigned)le32_to_cpu(data->sii.length));
1574987da915Sopenharmony_ci		break;
1575987da915Sopenharmony_ci	case INDEX_ATTR_SECURE_SDH:
1576987da915Sopenharmony_ci		ntfs_log_verbose("\t\tHash:\t\t\t 0x%08x\n",
1577987da915Sopenharmony_ci				(unsigned)le32_to_cpu(data->sdh.hash));
1578987da915Sopenharmony_ci		ntfs_log_verbose("\t\tSecurity id:\t\t %u (0x%x)\n",
1579987da915Sopenharmony_ci				(unsigned)le32_to_cpu(data->sdh.security_id),
1580987da915Sopenharmony_ci				(unsigned)le32_to_cpu(data->sdh.security_id));
1581987da915Sopenharmony_ci		ntfs_log_verbose("\t\tOffset in $SDS:\t\t %llu (0x%llx)\n",
1582987da915Sopenharmony_ci				(unsigned long long)
1583987da915Sopenharmony_ci				le64_to_cpu(data->sdh.offset),
1584987da915Sopenharmony_ci				(unsigned long long)
1585987da915Sopenharmony_ci				le64_to_cpu(data->sdh.offset));
1586987da915Sopenharmony_ci		ntfs_log_verbose("\t\tLength in $SDS:\t\t %u (0x%x)\n",
1587987da915Sopenharmony_ci				(unsigned)le32_to_cpu(data->sdh.length),
1588987da915Sopenharmony_ci				(unsigned)le32_to_cpu(data->sdh.length));
1589987da915Sopenharmony_ci		ntfs_log_verbose("\t\tUnknown (padding):\t 0x%08x\n",
1590987da915Sopenharmony_ci				(unsigned)le32_to_cpu(data->sdh.reserved_II));
1591987da915Sopenharmony_ci		break;
1592987da915Sopenharmony_ci	case INDEX_ATTR_OBJID_O: {
1593987da915Sopenharmony_ci		OBJ_ID_INDEX_DATA *object_id_data;
1594987da915Sopenharmony_ci		char printable_GUID[37];
1595987da915Sopenharmony_ci
1596987da915Sopenharmony_ci		object_id_data = (OBJ_ID_INDEX_DATA*)((u8*)entry +
1597987da915Sopenharmony_ci				le16_to_cpu(entry->data_offset));
1598987da915Sopenharmony_ci		ntfs_log_verbose("\t\tMFT Number:\t\t 0x%llx\n",
1599987da915Sopenharmony_ci				(unsigned long long)
1600987da915Sopenharmony_ci				MREF_LE(object_id_data->mft_reference));
1601987da915Sopenharmony_ci		ntfs_log_verbose("\t\tMFT Sequence Number:\t 0x%x\n",
1602987da915Sopenharmony_ci				(unsigned)
1603987da915Sopenharmony_ci				MSEQNO_LE(object_id_data->mft_reference));
1604987da915Sopenharmony_ci		ntfs_guid_to_mbs(&object_id_data->birth_volume_id,
1605987da915Sopenharmony_ci				printable_GUID);
1606987da915Sopenharmony_ci		ntfs_log_verbose("\t\tBirth volume id GUID:\t %s\n",
1607987da915Sopenharmony_ci				printable_GUID);
1608987da915Sopenharmony_ci		ntfs_guid_to_mbs(&object_id_data->birth_object_id,
1609987da915Sopenharmony_ci				printable_GUID);
1610987da915Sopenharmony_ci		ntfs_log_verbose("\t\tBirth object id GUID:\t %s\n",
1611987da915Sopenharmony_ci				printable_GUID);
1612987da915Sopenharmony_ci		ntfs_guid_to_mbs(&object_id_data->domain_id, printable_GUID);
1613987da915Sopenharmony_ci		ntfs_log_verbose("\t\tDomain id GUID:\t\t %s\n",
1614987da915Sopenharmony_ci				printable_GUID);
1615987da915Sopenharmony_ci		}
1616987da915Sopenharmony_ci		break;
1617987da915Sopenharmony_ci	case INDEX_ATTR_REPARSE_R:
1618987da915Sopenharmony_ci		/* TODO */
1619987da915Sopenharmony_ci		break;
1620987da915Sopenharmony_ci	case INDEX_ATTR_QUOTA_O:
1621987da915Sopenharmony_ci		ntfs_log_verbose("\t\tOwner id:\t\t %u (0x%x)\n",
1622987da915Sopenharmony_ci				(unsigned)le32_to_cpu(data->quota_o.owner_id),
1623987da915Sopenharmony_ci				(unsigned)le32_to_cpu(data->quota_o.owner_id));
1624987da915Sopenharmony_ci		ntfs_log_verbose("\t\tUnknown:\t\t %u (0x%x)\n",
1625987da915Sopenharmony_ci				(unsigned)le32_to_cpu(data->quota_o.unknown),
1626987da915Sopenharmony_ci				(unsigned)le32_to_cpu(data->quota_o.unknown));
1627987da915Sopenharmony_ci		break;
1628987da915Sopenharmony_ci	case INDEX_ATTR_QUOTA_Q:
1629987da915Sopenharmony_ci		ntfs_log_verbose("\t\tVersion:\t\t %u\n",
1630987da915Sopenharmony_ci				(unsigned)le32_to_cpu(data->quota_q.version));
1631987da915Sopenharmony_ci		ntfs_log_verbose("\t\tQuota flags:\t\t 0x%08x\n",
1632987da915Sopenharmony_ci				(unsigned)le32_to_cpu(data->quota_q.flags));
1633987da915Sopenharmony_ci		ntfs_log_verbose("\t\tBytes used:\t\t %llu (0x%llx)\n",
1634987da915Sopenharmony_ci				(unsigned long long)
1635987da915Sopenharmony_ci				le64_to_cpu(data->quota_q.bytes_used),
1636987da915Sopenharmony_ci				(unsigned long long)
1637987da915Sopenharmony_ci				le64_to_cpu(data->quota_q.bytes_used));
1638987da915Sopenharmony_ci		ntfs_log_verbose("\t\tLast changed:\t\t %s",
1639987da915Sopenharmony_ci				ntfsinfo_time_to_str(
1640987da915Sopenharmony_ci				data->quota_q.change_time));
1641987da915Sopenharmony_ci		ntfs_log_verbose("\t\tThreshold:\t\t %lld (0x%llx)\n",
1642987da915Sopenharmony_ci				(unsigned long long)
1643987da915Sopenharmony_ci				sle64_to_cpu(data->quota_q.threshold),
1644987da915Sopenharmony_ci				(unsigned long long)
1645987da915Sopenharmony_ci				sle64_to_cpu(data->quota_q.threshold));
1646987da915Sopenharmony_ci		ntfs_log_verbose("\t\tLimit:\t\t\t %lld (0x%llx)\n",
1647987da915Sopenharmony_ci				(unsigned long long)
1648987da915Sopenharmony_ci				sle64_to_cpu(data->quota_q.limit),
1649987da915Sopenharmony_ci				(unsigned long long)
1650987da915Sopenharmony_ci				sle64_to_cpu(data->quota_q.limit));
1651987da915Sopenharmony_ci		ntfs_log_verbose("\t\tExceeded time:\t\t %lld (0x%llx)\n",
1652987da915Sopenharmony_ci				(unsigned long long)
1653987da915Sopenharmony_ci				sle64_to_cpu(data->quota_q.exceeded_time),
1654987da915Sopenharmony_ci				(unsigned long long)
1655987da915Sopenharmony_ci				sle64_to_cpu(data->quota_q.exceeded_time));
1656987da915Sopenharmony_ci		if (le16_to_cpu(entry->data_length) > 48) {
1657987da915Sopenharmony_ci			char *sid;
1658987da915Sopenharmony_ci			sid = ntfs_sid_to_mbs(&data->quota_q.sid, NULL, 0);
1659987da915Sopenharmony_ci			ntfs_log_verbose("\t\tOwner SID:\t\t %s\n", sid);
1660987da915Sopenharmony_ci			free(sid);
1661987da915Sopenharmony_ci		}
1662987da915Sopenharmony_ci		break;
1663987da915Sopenharmony_ci	default:
1664987da915Sopenharmony_ci		ntfs_log_verbose("\t\tIndex attr type is UNKNOWN: \t 0x%08x\n",
1665987da915Sopenharmony_ci				(unsigned)type);
1666987da915Sopenharmony_ci		break;
1667987da915Sopenharmony_ci	}
1668987da915Sopenharmony_ci}
1669987da915Sopenharmony_ci
1670987da915Sopenharmony_ci/**
1671987da915Sopenharmony_ci * ntfs_dump_index_entries()
1672987da915Sopenharmony_ci *
1673987da915Sopenharmony_ci * dump sequence of index_entries and return number of entries dumped.
1674987da915Sopenharmony_ci */
1675987da915Sopenharmony_cistatic int ntfs_dump_index_entries(INDEX_ENTRY *entry, INDEX_ATTR_TYPE type)
1676987da915Sopenharmony_ci{
1677987da915Sopenharmony_ci	int numb_entries = 1;
1678987da915Sopenharmony_ci	while (1) {
1679987da915Sopenharmony_ci		if (!opts.verbose) {
1680987da915Sopenharmony_ci			if (entry->ie_flags & INDEX_ENTRY_END)
1681987da915Sopenharmony_ci				break;
1682987da915Sopenharmony_ci			entry = (INDEX_ENTRY *)((u8 *)entry +
1683987da915Sopenharmony_ci						le16_to_cpu(entry->length));
1684987da915Sopenharmony_ci			numb_entries++;
1685987da915Sopenharmony_ci			continue;
1686987da915Sopenharmony_ci		}
1687987da915Sopenharmony_ci		ntfs_log_verbose("\t\tEntry length:\t\t %u (0x%x)\n",
1688987da915Sopenharmony_ci				(unsigned)le16_to_cpu(entry->length),
1689987da915Sopenharmony_ci				(unsigned)le16_to_cpu(entry->length));
1690987da915Sopenharmony_ci		ntfs_log_verbose("\t\tKey length:\t\t %u (0x%x)\n",
1691987da915Sopenharmony_ci				(unsigned)le16_to_cpu(entry->key_length),
1692987da915Sopenharmony_ci				(unsigned)le16_to_cpu(entry->key_length));
1693987da915Sopenharmony_ci		ntfs_log_verbose("\t\tIndex entry flags:\t 0x%02x\n",
1694987da915Sopenharmony_ci				(unsigned)le16_to_cpu(entry->ie_flags));
1695987da915Sopenharmony_ci
1696987da915Sopenharmony_ci		if (entry->ie_flags & INDEX_ENTRY_NODE)
1697987da915Sopenharmony_ci			ntfs_log_verbose("\t\tSubnode VCN:\t\t %lld (0x%llx)\n",
1698987da915Sopenharmony_ci					 (long long)ntfs_ie_get_vcn(entry),
1699987da915Sopenharmony_ci					 (long long)ntfs_ie_get_vcn(entry));
1700987da915Sopenharmony_ci		if (entry->ie_flags & INDEX_ENTRY_END)
1701987da915Sopenharmony_ci			break;
1702987da915Sopenharmony_ci
1703987da915Sopenharmony_ci		switch (type) {
1704987da915Sopenharmony_ci		case INDEX_ATTR_DIRECTORY_I30:
1705987da915Sopenharmony_ci			ntfs_log_verbose("\t\tFILE record number:\t %llu "
1706987da915Sopenharmony_ci					"(0x%llx)\n", (unsigned long long)
1707987da915Sopenharmony_ci					MREF_LE(entry->indexed_file),
1708987da915Sopenharmony_ci					(unsigned long long)
1709987da915Sopenharmony_ci					MREF_LE(entry->indexed_file));
1710987da915Sopenharmony_ci			ntfs_dump_filename("\t\t", &entry->key.file_name);
1711987da915Sopenharmony_ci			break;
1712987da915Sopenharmony_ci		default:
1713987da915Sopenharmony_ci			ntfs_log_verbose("\t\tData offset:\t\t %u (0x%x)\n",
1714987da915Sopenharmony_ci					(unsigned)
1715987da915Sopenharmony_ci					le16_to_cpu(entry->data_offset),
1716987da915Sopenharmony_ci					(unsigned)
1717987da915Sopenharmony_ci					le16_to_cpu(entry->data_offset));
1718987da915Sopenharmony_ci			ntfs_log_verbose("\t\tData length:\t\t %u (0x%x)\n",
1719987da915Sopenharmony_ci					(unsigned)
1720987da915Sopenharmony_ci					le16_to_cpu(entry->data_length),
1721987da915Sopenharmony_ci					(unsigned)
1722987da915Sopenharmony_ci					le16_to_cpu(entry->data_length));
1723987da915Sopenharmony_ci			ntfs_dump_index_key(entry, type);
1724987da915Sopenharmony_ci			ntfs_log_verbose("\t\tKey Data:\n");
1725987da915Sopenharmony_ci			ntfs_dump_index_data(entry, type);
1726987da915Sopenharmony_ci			break;
1727987da915Sopenharmony_ci		}
1728987da915Sopenharmony_ci		if (!entry->length) {
1729987da915Sopenharmony_ci			ntfs_log_verbose("\tWARNING: Corrupt index entry, "
1730987da915Sopenharmony_ci					"skipping the remainder of this index "
1731987da915Sopenharmony_ci					"block.\n");
1732987da915Sopenharmony_ci			break;
1733987da915Sopenharmony_ci		}
1734987da915Sopenharmony_ci		entry = (INDEX_ENTRY*)((u8*)entry + le16_to_cpu(entry->length));
1735987da915Sopenharmony_ci		numb_entries++;
1736987da915Sopenharmony_ci		ntfs_log_verbose("\n");
1737987da915Sopenharmony_ci	}
1738987da915Sopenharmony_ci	ntfs_log_verbose("\tEnd of index block reached\n");
1739987da915Sopenharmony_ci	return numb_entries;
1740987da915Sopenharmony_ci}
1741987da915Sopenharmony_ci
1742987da915Sopenharmony_ci#define	COMPARE_INDEX_NAMES(attr, name)					       \
1743987da915Sopenharmony_ci	ntfs_names_are_equal((name), sizeof(name) / 2 - 1,		       \
1744987da915Sopenharmony_ci		(ntfschar*)((char*)(attr) + le16_to_cpu((attr)->name_offset)), \
1745987da915Sopenharmony_ci		(attr)->name_length, CASE_SENSITIVE, NULL, 0)
1746987da915Sopenharmony_ci
1747987da915Sopenharmony_cistatic INDEX_ATTR_TYPE get_index_attr_type(ntfs_inode *ni, ATTR_RECORD *attr,
1748987da915Sopenharmony_ci					   INDEX_ROOT *index_root)
1749987da915Sopenharmony_ci{
1750987da915Sopenharmony_ci	char file_name[64];
1751987da915Sopenharmony_ci
1752987da915Sopenharmony_ci	if (!attr->name_length)
1753987da915Sopenharmony_ci		return INDEX_ATTR_UNKNOWN;
1754987da915Sopenharmony_ci
1755987da915Sopenharmony_ci	if (index_root->type) {
1756987da915Sopenharmony_ci		if (index_root->type == AT_FILE_NAME)
1757987da915Sopenharmony_ci			return INDEX_ATTR_DIRECTORY_I30;
1758987da915Sopenharmony_ci		else
1759987da915Sopenharmony_ci			/* weird, this should be illegal */
1760987da915Sopenharmony_ci			ntfs_log_error("Unknown index attribute type: 0x%0X\n",
1761987da915Sopenharmony_ci				       le32_to_cpu(index_root->type));
1762987da915Sopenharmony_ci		return INDEX_ATTR_UNKNOWN;
1763987da915Sopenharmony_ci	}
1764987da915Sopenharmony_ci
1765987da915Sopenharmony_ci	if (utils_is_metadata(ni) <= 0)
1766987da915Sopenharmony_ci		return INDEX_ATTR_UNKNOWN;
1767987da915Sopenharmony_ci	if (utils_inode_get_name(ni, file_name, sizeof(file_name)) <= 0)
1768987da915Sopenharmony_ci		return INDEX_ATTR_UNKNOWN;
1769987da915Sopenharmony_ci
1770987da915Sopenharmony_ci	if (COMPARE_INDEX_NAMES(attr, NTFS_INDEX_SDH))
1771987da915Sopenharmony_ci		return INDEX_ATTR_SECURE_SDH;
1772987da915Sopenharmony_ci	else if (COMPARE_INDEX_NAMES(attr, NTFS_INDEX_SII))
1773987da915Sopenharmony_ci		return INDEX_ATTR_SECURE_SII;
1774987da915Sopenharmony_ci	else if (COMPARE_INDEX_NAMES(attr, NTFS_INDEX_SII))
1775987da915Sopenharmony_ci		return INDEX_ATTR_SECURE_SII;
1776987da915Sopenharmony_ci	else if (COMPARE_INDEX_NAMES(attr, NTFS_INDEX_Q))
1777987da915Sopenharmony_ci		return INDEX_ATTR_QUOTA_Q;
1778987da915Sopenharmony_ci	else if (COMPARE_INDEX_NAMES(attr, NTFS_INDEX_R))
1779987da915Sopenharmony_ci		return INDEX_ATTR_REPARSE_R;
1780987da915Sopenharmony_ci	else if (COMPARE_INDEX_NAMES(attr, NTFS_INDEX_O)) {
1781987da915Sopenharmony_ci		if (!strcmp(file_name, "/$Extend/$Quota"))
1782987da915Sopenharmony_ci			return INDEX_ATTR_QUOTA_O;
1783987da915Sopenharmony_ci		else if (!strcmp(file_name, "/$Extend/$ObjId"))
1784987da915Sopenharmony_ci			return INDEX_ATTR_OBJID_O;
1785987da915Sopenharmony_ci	}
1786987da915Sopenharmony_ci
1787987da915Sopenharmony_ci	return INDEX_ATTR_UNKNOWN;
1788987da915Sopenharmony_ci}
1789987da915Sopenharmony_ci
1790987da915Sopenharmony_cistatic void ntfs_dump_index_attr_type(INDEX_ATTR_TYPE type)
1791987da915Sopenharmony_ci{
1792987da915Sopenharmony_ci	if (type == INDEX_ATTR_DIRECTORY_I30)
1793987da915Sopenharmony_ci		printf("DIRECTORY_I30");
1794987da915Sopenharmony_ci	else if (type == INDEX_ATTR_SECURE_SDH)
1795987da915Sopenharmony_ci		printf("SECURE_SDH");
1796987da915Sopenharmony_ci	else if (type == INDEX_ATTR_SECURE_SII)
1797987da915Sopenharmony_ci		printf("SECURE_SII");
1798987da915Sopenharmony_ci	else if (type == INDEX_ATTR_OBJID_O)
1799987da915Sopenharmony_ci		printf("OBJID_O");
1800987da915Sopenharmony_ci	else if (type == INDEX_ATTR_QUOTA_O)
1801987da915Sopenharmony_ci		printf("QUOTA_O");
1802987da915Sopenharmony_ci	else if (type == INDEX_ATTR_QUOTA_Q)
1803987da915Sopenharmony_ci		printf("QUOTA_Q");
1804987da915Sopenharmony_ci	else if (type == INDEX_ATTR_REPARSE_R)
1805987da915Sopenharmony_ci		printf("REPARSE_R");
1806987da915Sopenharmony_ci	else
1807987da915Sopenharmony_ci		printf("UNKNOWN");
1808987da915Sopenharmony_ci	printf("\n");
1809987da915Sopenharmony_ci}
1810987da915Sopenharmony_ci
1811987da915Sopenharmony_cistatic void ntfs_dump_index_header(const char *indent, INDEX_HEADER *idx)
1812987da915Sopenharmony_ci{
1813987da915Sopenharmony_ci	printf("%sEntries Offset:\t\t %u (0x%x)\n", indent,
1814987da915Sopenharmony_ci			(unsigned)le32_to_cpu(idx->entries_offset),
1815987da915Sopenharmony_ci			(unsigned)le32_to_cpu(idx->entries_offset));
1816987da915Sopenharmony_ci	printf("%sIndex Size:\t\t %u (0x%x)\n", indent,
1817987da915Sopenharmony_ci			(unsigned)le32_to_cpu(idx->index_length),
1818987da915Sopenharmony_ci			(unsigned)le32_to_cpu(idx->index_length));
1819987da915Sopenharmony_ci	printf("%sAllocated Size:\t\t %u (0x%x)\n", indent,
1820987da915Sopenharmony_ci			(unsigned)le32_to_cpu(idx->allocated_size),
1821987da915Sopenharmony_ci			(unsigned)le32_to_cpu(idx->allocated_size));
1822987da915Sopenharmony_ci	printf("%sIndex header flags:\t 0x%02x\n", indent, idx->ih_flags);
1823987da915Sopenharmony_ci
1824987da915Sopenharmony_ci	/* FIXME: there are 3 reserved bytes here */
1825987da915Sopenharmony_ci}
1826987da915Sopenharmony_ci
1827987da915Sopenharmony_ci/**
1828987da915Sopenharmony_ci * ntfs_dump_attr_index_root()
1829987da915Sopenharmony_ci *
1830987da915Sopenharmony_ci * dump the index_root attribute
1831987da915Sopenharmony_ci */
1832987da915Sopenharmony_cistatic void ntfs_dump_attr_index_root(ATTR_RECORD *attr, ntfs_inode *ni)
1833987da915Sopenharmony_ci{
1834987da915Sopenharmony_ci	INDEX_ATTR_TYPE type;
1835987da915Sopenharmony_ci	INDEX_ROOT *index_root = NULL;
1836987da915Sopenharmony_ci	INDEX_ENTRY *entry;
1837987da915Sopenharmony_ci
1838987da915Sopenharmony_ci	index_root = (INDEX_ROOT*)((u8*)attr + le16_to_cpu(attr->value_offset));
1839987da915Sopenharmony_ci
1840987da915Sopenharmony_ci	/* attr_type dumping */
1841987da915Sopenharmony_ci	type = get_index_attr_type(ni, attr, index_root);
1842987da915Sopenharmony_ci	printf("\tIndexed Attr Type:\t ");
1843987da915Sopenharmony_ci	ntfs_dump_index_attr_type(type);
1844987da915Sopenharmony_ci
1845987da915Sopenharmony_ci	/* collation rule dumping */
1846987da915Sopenharmony_ci	printf("\tCollation Rule:\t\t %u (0x%x)\n",
1847987da915Sopenharmony_ci			(unsigned)le32_to_cpu(index_root->collation_rule),
1848987da915Sopenharmony_ci			(unsigned)le32_to_cpu(index_root->collation_rule));
1849987da915Sopenharmony_ci/*	COLLATION_BINARY, COLLATION_FILE_NAME, COLLATION_UNICODE_STRING,
1850987da915Sopenharmony_ci	COLLATION_NTOFS_ULONG, COLLATION_NTOFS_SID,
1851987da915Sopenharmony_ci	COLLATION_NTOFS_SECURITY_HASH, COLLATION_NTOFS_ULONGS */
1852987da915Sopenharmony_ci
1853987da915Sopenharmony_ci	printf("\tIndex Block Size:\t %u (0x%x)\n",
1854987da915Sopenharmony_ci			(unsigned)le32_to_cpu(index_root->index_block_size),
1855987da915Sopenharmony_ci			(unsigned)le32_to_cpu(index_root->index_block_size));
1856987da915Sopenharmony_ci	if (le32_to_cpu(index_root->index_block_size) < ni->vol->cluster_size)
1857987da915Sopenharmony_ci		printf("\t512-byte Units Per Block:\t %u (0x%x)\n",
1858987da915Sopenharmony_ci			(unsigned)index_root->clusters_per_index_block,
1859987da915Sopenharmony_ci			(unsigned)index_root->clusters_per_index_block);
1860987da915Sopenharmony_ci	else
1861987da915Sopenharmony_ci		printf("\tClusters Per Block:\t %u (0x%x)\n",
1862987da915Sopenharmony_ci			(unsigned)index_root->clusters_per_index_block,
1863987da915Sopenharmony_ci			(unsigned)index_root->clusters_per_index_block);
1864987da915Sopenharmony_ci
1865987da915Sopenharmony_ci	ntfs_dump_index_header("\t", &index_root->index);
1866987da915Sopenharmony_ci
1867987da915Sopenharmony_ci	entry = (INDEX_ENTRY*)((u8*)index_root +
1868987da915Sopenharmony_ci			le32_to_cpu(index_root->index.entries_offset) + 0x10);
1869987da915Sopenharmony_ci	ntfs_log_verbose("\tDumping index root:\n");
1870987da915Sopenharmony_ci	printf("\tIndex entries total:\t %d\n",
1871987da915Sopenharmony_ci			ntfs_dump_index_entries(entry, type));
1872987da915Sopenharmony_ci}
1873987da915Sopenharmony_ci
1874987da915Sopenharmony_cistatic void ntfs_dump_usa_lsn(const char *indent, MFT_RECORD *mrec)
1875987da915Sopenharmony_ci{
1876987da915Sopenharmony_ci	printf("%sUpd. Seq. Array Off.:\t %u (0x%x)\n", indent,
1877987da915Sopenharmony_ci			(unsigned)le16_to_cpu(mrec->usa_ofs),
1878987da915Sopenharmony_ci			(unsigned)le16_to_cpu(mrec->usa_ofs));
1879987da915Sopenharmony_ci	printf("%sUpd. Seq. Array Count:\t %u (0x%x)\n", indent,
1880987da915Sopenharmony_ci			(unsigned)le16_to_cpu(mrec->usa_count),
1881987da915Sopenharmony_ci			(unsigned)le16_to_cpu(mrec->usa_count));
1882987da915Sopenharmony_ci	printf("%sUpd. Seq. Number:\t %u (0x%x)\n", indent,
1883987da915Sopenharmony_ci			(unsigned)le16_to_cpup((le16*)((u8*)mrec +
1884987da915Sopenharmony_ci				le16_to_cpu(mrec->usa_ofs))),
1885987da915Sopenharmony_ci			(unsigned)le16_to_cpup((le16*)((u8*)mrec +
1886987da915Sopenharmony_ci				le16_to_cpu(mrec->usa_ofs))));
1887987da915Sopenharmony_ci	printf("%sLogFile Seq. Number:\t 0x%llx\n", indent,
1888987da915Sopenharmony_ci			(unsigned long long)sle64_to_cpu(mrec->lsn));
1889987da915Sopenharmony_ci}
1890987da915Sopenharmony_ci
1891987da915Sopenharmony_ci
1892987da915Sopenharmony_cistatic s32 ntfs_dump_index_block(INDEX_BLOCK *ib, INDEX_ATTR_TYPE type,
1893987da915Sopenharmony_ci		u32 ib_size)
1894987da915Sopenharmony_ci{
1895987da915Sopenharmony_ci	INDEX_ENTRY *entry;
1896987da915Sopenharmony_ci
1897987da915Sopenharmony_ci	if (ntfs_mst_post_read_fixup((NTFS_RECORD*)ib, ib_size)) {
1898987da915Sopenharmony_ci		ntfs_log_perror("Damaged INDX record");
1899987da915Sopenharmony_ci		return -1;
1900987da915Sopenharmony_ci	}
1901987da915Sopenharmony_ci	ntfs_log_verbose("\tDumping index block:\n");
1902987da915Sopenharmony_ci	if (opts.verbose)
1903987da915Sopenharmony_ci		ntfs_dump_usa_lsn("\t\t", (MFT_RECORD*)ib);
1904987da915Sopenharmony_ci
1905987da915Sopenharmony_ci	ntfs_log_verbose("\t\tNode VCN:\t\t %lld (0x%llx)\n",
1906987da915Sopenharmony_ci			(unsigned long long)sle64_to_cpu(ib->index_block_vcn),
1907987da915Sopenharmony_ci			(unsigned long long)sle64_to_cpu(ib->index_block_vcn));
1908987da915Sopenharmony_ci
1909987da915Sopenharmony_ci	entry = (INDEX_ENTRY*)((u8*)ib +
1910987da915Sopenharmony_ci				le32_to_cpu(ib->index.entries_offset) + 0x18);
1911987da915Sopenharmony_ci
1912987da915Sopenharmony_ci	if (opts.verbose) {
1913987da915Sopenharmony_ci		ntfs_dump_index_header("\t\t", &ib->index);
1914987da915Sopenharmony_ci		printf("\n");
1915987da915Sopenharmony_ci	}
1916987da915Sopenharmony_ci
1917987da915Sopenharmony_ci	return ntfs_dump_index_entries(entry, type);
1918987da915Sopenharmony_ci}
1919987da915Sopenharmony_ci
1920987da915Sopenharmony_ci/**
1921987da915Sopenharmony_ci * ntfs_dump_attr_index_allocation()
1922987da915Sopenharmony_ci *
1923987da915Sopenharmony_ci * dump context of the index_allocation attribute
1924987da915Sopenharmony_ci */
1925987da915Sopenharmony_cistatic void ntfs_dump_attr_index_allocation(ATTR_RECORD *attr, ntfs_inode *ni)
1926987da915Sopenharmony_ci{
1927987da915Sopenharmony_ci	INDEX_ALLOCATION *allocation, *tmp_alloc;
1928987da915Sopenharmony_ci	INDEX_ROOT *ir;
1929987da915Sopenharmony_ci	INDEX_ATTR_TYPE type;
1930987da915Sopenharmony_ci	int total_entries = 0;
1931987da915Sopenharmony_ci	int total_indx_blocks = 0;
1932987da915Sopenharmony_ci	u8 *bitmap, *byte;
1933987da915Sopenharmony_ci	int bit;
1934987da915Sopenharmony_ci	ntfschar *name;
1935987da915Sopenharmony_ci	u32 name_len;
1936987da915Sopenharmony_ci	s64 data_size;
1937987da915Sopenharmony_ci
1938987da915Sopenharmony_ci	ir = ntfs_index_root_get(ni, attr);
1939987da915Sopenharmony_ci	if (!ir) {
1940987da915Sopenharmony_ci		ntfs_log_perror("Failed to read $INDEX_ROOT attribute");
1941987da915Sopenharmony_ci		return;
1942987da915Sopenharmony_ci	}
1943987da915Sopenharmony_ci
1944987da915Sopenharmony_ci	type = get_index_attr_type(ni, attr, ir);
1945987da915Sopenharmony_ci
1946987da915Sopenharmony_ci	name = (ntfschar *)((u8 *)attr + le16_to_cpu(attr->name_offset));
1947987da915Sopenharmony_ci	name_len = attr->name_length;
1948987da915Sopenharmony_ci
1949987da915Sopenharmony_ci	byte = bitmap = ntfs_attr_readall(ni, AT_BITMAP, name, name_len, NULL);
1950987da915Sopenharmony_ci	if (!byte) {
1951987da915Sopenharmony_ci		ntfs_log_perror("Failed to read $BITMAP attribute");
1952987da915Sopenharmony_ci		goto out_index_root;
1953987da915Sopenharmony_ci	}
1954987da915Sopenharmony_ci
1955987da915Sopenharmony_ci	tmp_alloc = allocation = ntfs_attr_readall(ni, AT_INDEX_ALLOCATION,
1956987da915Sopenharmony_ci						   name, name_len, &data_size);
1957987da915Sopenharmony_ci	if (!tmp_alloc) {
1958987da915Sopenharmony_ci		ntfs_log_perror("Failed to read $INDEX_ALLOCATION attribute");
1959987da915Sopenharmony_ci		goto out_bitmap;
1960987da915Sopenharmony_ci	}
1961987da915Sopenharmony_ci
1962987da915Sopenharmony_ci	bit = 0;
1963987da915Sopenharmony_ci	while ((u8 *)tmp_alloc < (u8 *)allocation + data_size) {
1964987da915Sopenharmony_ci		if (*byte & (1 << bit)) {
1965987da915Sopenharmony_ci			int entries;
1966987da915Sopenharmony_ci
1967987da915Sopenharmony_ci			entries = ntfs_dump_index_block(tmp_alloc, type,
1968987da915Sopenharmony_ci							le32_to_cpu(
1969987da915Sopenharmony_ci							ir->index_block_size));
1970987da915Sopenharmony_ci	       		if (entries != -1) {
1971987da915Sopenharmony_ci				total_entries += entries;
1972987da915Sopenharmony_ci				total_indx_blocks++;
1973987da915Sopenharmony_ci				ntfs_log_verbose("\tIndex entries:\t\t %d\n",
1974987da915Sopenharmony_ci						entries);
1975987da915Sopenharmony_ci			}
1976987da915Sopenharmony_ci		}
1977987da915Sopenharmony_ci		tmp_alloc = (INDEX_ALLOCATION *)((u8 *)tmp_alloc +
1978987da915Sopenharmony_ci						le32_to_cpu(
1979987da915Sopenharmony_ci						ir->index_block_size));
1980987da915Sopenharmony_ci		bit++;
1981987da915Sopenharmony_ci		if (bit > 7) {
1982987da915Sopenharmony_ci			bit = 0;
1983987da915Sopenharmony_ci			byte++;
1984987da915Sopenharmony_ci		}
1985987da915Sopenharmony_ci	}
1986987da915Sopenharmony_ci
1987987da915Sopenharmony_ci	printf("\tIndex entries total:\t %d\n", total_entries);
1988987da915Sopenharmony_ci	printf("\tINDX blocks total:\t %d\n", total_indx_blocks);
1989987da915Sopenharmony_ci
1990987da915Sopenharmony_ci	free(allocation);
1991987da915Sopenharmony_ciout_bitmap:
1992987da915Sopenharmony_ci	free(bitmap);
1993987da915Sopenharmony_ciout_index_root:
1994987da915Sopenharmony_ci	free(ir);
1995987da915Sopenharmony_ci}
1996987da915Sopenharmony_ci
1997987da915Sopenharmony_ci/**
1998987da915Sopenharmony_ci * ntfs_dump_attr_bitmap()
1999987da915Sopenharmony_ci *
2000987da915Sopenharmony_ci * dump the bitmap attribute
2001987da915Sopenharmony_ci */
2002987da915Sopenharmony_cistatic void ntfs_dump_attr_bitmap(ATTR_RECORD *attr __attribute__((unused)))
2003987da915Sopenharmony_ci{
2004987da915Sopenharmony_ci	/* TODO */
2005987da915Sopenharmony_ci}
2006987da915Sopenharmony_ci
2007987da915Sopenharmony_ci/**
2008987da915Sopenharmony_ci * ntfs_dump_attr_reparse_point()
2009987da915Sopenharmony_ci *
2010987da915Sopenharmony_ci * of ntfs 3.x dumps the reparse_point attribute
2011987da915Sopenharmony_ci */
2012987da915Sopenharmony_cistatic void ntfs_dump_attr_reparse_point(ATTR_RECORD *attr
2013987da915Sopenharmony_ci			__attribute__((unused)), ntfs_inode *inode)
2014987da915Sopenharmony_ci{
2015987da915Sopenharmony_ci	REPARSE_POINT *reparse;
2016987da915Sopenharmony_ci	le32 tag;
2017987da915Sopenharmony_ci	const char *name;
2018987da915Sopenharmony_ci	u8 *pvalue;
2019987da915Sopenharmony_ci	s64 size;
2020987da915Sopenharmony_ci	unsigned int length;
2021987da915Sopenharmony_ci	unsigned int cnt;
2022987da915Sopenharmony_ci
2023987da915Sopenharmony_ci	if (attr->non_resident) {
2024987da915Sopenharmony_ci		reparse = ntfs_attr_readall(inode, AT_REPARSE_POINT,
2025987da915Sopenharmony_ci						(ntfschar*)NULL, 0, &size);
2026987da915Sopenharmony_ci	} else {
2027987da915Sopenharmony_ci		reparse = (REPARSE_POINT*)((u8*)attr +
2028987da915Sopenharmony_ci				le16_to_cpu(attr->value_offset));
2029987da915Sopenharmony_ci	}
2030987da915Sopenharmony_ci	if (reparse) {
2031987da915Sopenharmony_ci		tag = reparse->reparse_tag;
2032987da915Sopenharmony_ci		name = reparse_type_name(tag);
2033987da915Sopenharmony_ci		printf("\tReparse tag:\t\t 0x%08lx%s\n",
2034987da915Sopenharmony_ci			(long)le32_to_cpu(tag),name);
2035987da915Sopenharmony_ci		length = le16_to_cpu(reparse->reparse_data_length);
2036987da915Sopenharmony_ci		printf("\tData length:\t\t %u (0x%x)\n",
2037987da915Sopenharmony_ci			(unsigned int)length,(unsigned int)length);
2038987da915Sopenharmony_ci		cnt = length;
2039987da915Sopenharmony_ci		pvalue = reparse->reparse_data;
2040987da915Sopenharmony_ci		printf("\tData:\t\t\t");
2041987da915Sopenharmony_ci		printf(cnt ? " 0x" : "(NONE)");
2042987da915Sopenharmony_ci		if (cnt > 32)
2043987da915Sopenharmony_ci			cnt = 32;
2044987da915Sopenharmony_ci		while (cnt-- > 0)
2045987da915Sopenharmony_ci			printf("%02x",*pvalue++);
2046987da915Sopenharmony_ci		if (length > 32)
2047987da915Sopenharmony_ci			printf("...\n");
2048987da915Sopenharmony_ci		else
2049987da915Sopenharmony_ci			printf("\n");
2050987da915Sopenharmony_ci		if (attr->non_resident)
2051987da915Sopenharmony_ci			free(reparse);
2052987da915Sopenharmony_ci	} else {
2053987da915Sopenharmony_ci		ntfs_log_perror("Failed to get the reparse data");
2054987da915Sopenharmony_ci	}
2055987da915Sopenharmony_ci}
2056987da915Sopenharmony_ci
2057987da915Sopenharmony_ci/**
2058987da915Sopenharmony_ci * ntfs_dump_attr_ea_information()
2059987da915Sopenharmony_ci *
2060987da915Sopenharmony_ci * dump the ea_information attribute
2061987da915Sopenharmony_ci */
2062987da915Sopenharmony_cistatic void ntfs_dump_attr_ea_information(ATTR_RECORD *attr)
2063987da915Sopenharmony_ci{
2064987da915Sopenharmony_ci	EA_INFORMATION *ea_info;
2065987da915Sopenharmony_ci
2066987da915Sopenharmony_ci	ea_info = (EA_INFORMATION*)((u8*)attr +
2067987da915Sopenharmony_ci			le16_to_cpu(attr->value_offset));
2068987da915Sopenharmony_ci	printf("\tPacked EA length:\t %u (0x%x)\n",
2069987da915Sopenharmony_ci			(unsigned)le16_to_cpu(ea_info->ea_length),
2070987da915Sopenharmony_ci			(unsigned)le16_to_cpu(ea_info->ea_length));
2071987da915Sopenharmony_ci	printf("\tNEED_EA count:\t\t %u (0x%x)\n",
2072987da915Sopenharmony_ci			(unsigned)le16_to_cpu(ea_info->need_ea_count),
2073987da915Sopenharmony_ci			(unsigned)le16_to_cpu(ea_info->need_ea_count));
2074987da915Sopenharmony_ci	printf("\tUnpacked EA length:\t %u (0x%x)\n",
2075987da915Sopenharmony_ci			(unsigned)le32_to_cpu(ea_info->ea_query_length),
2076987da915Sopenharmony_ci			(unsigned)le32_to_cpu(ea_info->ea_query_length));
2077987da915Sopenharmony_ci}
2078987da915Sopenharmony_ci
2079987da915Sopenharmony_ci/**
2080987da915Sopenharmony_ci * ntfs_dump_attr_ea()
2081987da915Sopenharmony_ci *
2082987da915Sopenharmony_ci * dump the ea attribute
2083987da915Sopenharmony_ci */
2084987da915Sopenharmony_cistatic void ntfs_dump_attr_ea(ATTR_RECORD *attr, ntfs_volume *vol)
2085987da915Sopenharmony_ci{
2086987da915Sopenharmony_ci	const EA_ATTR *ea;
2087987da915Sopenharmony_ci	const u8 *pvalue;
2088987da915Sopenharmony_ci	u8 *buf = NULL;
2089987da915Sopenharmony_ci	const le32 *pval;
2090987da915Sopenharmony_ci	int offset;
2091987da915Sopenharmony_ci	int cnt;
2092987da915Sopenharmony_ci	s64 data_size;
2093987da915Sopenharmony_ci
2094987da915Sopenharmony_ci	if (attr->non_resident) {
2095987da915Sopenharmony_ci		runlist *rl;
2096987da915Sopenharmony_ci
2097987da915Sopenharmony_ci		data_size = sle64_to_cpu(attr->data_size);
2098987da915Sopenharmony_ci		if (!opts.verbose)
2099987da915Sopenharmony_ci			return;
2100987da915Sopenharmony_ci		/* FIXME: We don't handle fragmented mapping pairs case. */
2101987da915Sopenharmony_ci		rl = ntfs_mapping_pairs_decompress(vol, attr, NULL);
2102987da915Sopenharmony_ci		if (rl) {
2103987da915Sopenharmony_ci			s64 bytes_read;
2104987da915Sopenharmony_ci
2105987da915Sopenharmony_ci			buf = ntfs_malloc(data_size);
2106987da915Sopenharmony_ci			if (!buf) {
2107987da915Sopenharmony_ci				free(rl);
2108987da915Sopenharmony_ci				return;
2109987da915Sopenharmony_ci			}
2110987da915Sopenharmony_ci			bytes_read = ntfs_rl_pread(vol, rl, 0, data_size, buf);
2111987da915Sopenharmony_ci			if (bytes_read != data_size) {
2112987da915Sopenharmony_ci				ntfs_log_perror("ntfs_rl_pread failed");
2113987da915Sopenharmony_ci				free(buf);
2114987da915Sopenharmony_ci				free(rl);
2115987da915Sopenharmony_ci				return;
2116987da915Sopenharmony_ci			}
2117987da915Sopenharmony_ci			free(rl);
2118987da915Sopenharmony_ci			ea = (EA_ATTR*)buf;
2119987da915Sopenharmony_ci		} else {
2120987da915Sopenharmony_ci			ntfs_log_perror("ntfs_mapping_pairs_decompress failed");
2121987da915Sopenharmony_ci			return;
2122987da915Sopenharmony_ci		}
2123987da915Sopenharmony_ci	} else {
2124987da915Sopenharmony_ci		data_size = le32_to_cpu(attr->value_length);
2125987da915Sopenharmony_ci		if (!opts.verbose)
2126987da915Sopenharmony_ci			return;
2127987da915Sopenharmony_ci		ea = (EA_ATTR*)((u8*)attr + le16_to_cpu(attr->value_offset));
2128987da915Sopenharmony_ci	}
2129987da915Sopenharmony_ci	offset = 0;
2130987da915Sopenharmony_ci	while (1) {
2131987da915Sopenharmony_ci		printf("\n\tEA flags:\t\t ");
2132987da915Sopenharmony_ci		if (ea->flags) {
2133987da915Sopenharmony_ci			if (ea->flags == NEED_EA)
2134987da915Sopenharmony_ci				printf("NEED_EA\n");
2135987da915Sopenharmony_ci			else
2136987da915Sopenharmony_ci				printf("Unknown (0x%02x)\n",
2137987da915Sopenharmony_ci						(unsigned)ea->flags);
2138987da915Sopenharmony_ci		} else
2139987da915Sopenharmony_ci			printf("NONE\n");
2140987da915Sopenharmony_ci		printf("\tName length:\t %d (0x%x)\n",
2141987da915Sopenharmony_ci				(unsigned)ea->name_length,
2142987da915Sopenharmony_ci				(unsigned)ea->name_length);
2143987da915Sopenharmony_ci		printf("\tValue length:\t %d (0x%x)\n",
2144987da915Sopenharmony_ci				(unsigned)le16_to_cpu(ea->value_length),
2145987da915Sopenharmony_ci				(unsigned)le16_to_cpu(ea->value_length));
2146987da915Sopenharmony_ci			/* Name expected to be null terminated ? */
2147987da915Sopenharmony_ci		printf("\tName:\t\t '%s'\n", ea->name);
2148987da915Sopenharmony_ci		printf("\tValue:\t\t ");
2149987da915Sopenharmony_ci		if (ea->name_length == 11 &&
2150987da915Sopenharmony_ci				!strncmp((const char*)"SETFILEBITS",
2151987da915Sopenharmony_ci				(const char*)ea->name, 11)) {
2152987da915Sopenharmony_ci			pval = (const le32*)(ea->value + ea->name_length + 1);
2153987da915Sopenharmony_ci			printf("0%lo\n", (unsigned long)le32_to_cpu(*pval));
2154987da915Sopenharmony_ci		} else {
2155987da915Sopenharmony_ci			/* No alignment for value */
2156987da915Sopenharmony_ci			pvalue = ea->value + ea->name_length + 1;
2157987da915Sopenharmony_ci			/* Hex show a maximum of 32 bytes */
2158987da915Sopenharmony_ci			cnt = le16_to_cpu(ea->value_length);
2159987da915Sopenharmony_ci			printf(cnt ? "0x" : "(NONE)");
2160987da915Sopenharmony_ci			if (cnt > 32)
2161987da915Sopenharmony_ci				cnt = 32;
2162987da915Sopenharmony_ci			while (cnt-- > 0)
2163987da915Sopenharmony_ci				printf("%02x",*pvalue++);
2164987da915Sopenharmony_ci			if (le16_to_cpu(ea->value_length) > 32)
2165987da915Sopenharmony_ci				printf("...\n");
2166987da915Sopenharmony_ci			else
2167987da915Sopenharmony_ci				printf("\n");
2168987da915Sopenharmony_ci		}
2169987da915Sopenharmony_ci		if (ea->next_entry_offset) {
2170987da915Sopenharmony_ci			offset += le32_to_cpu(ea->next_entry_offset);
2171987da915Sopenharmony_ci			ea = (const EA_ATTR*)((const u8*)ea
2172987da915Sopenharmony_ci					+ le32_to_cpu(ea->next_entry_offset));
2173987da915Sopenharmony_ci		} else
2174987da915Sopenharmony_ci			break;
2175987da915Sopenharmony_ci		if (offset >= data_size)
2176987da915Sopenharmony_ci			break;
2177987da915Sopenharmony_ci	}
2178987da915Sopenharmony_ci	free(buf);
2179987da915Sopenharmony_ci}
2180987da915Sopenharmony_ci
2181987da915Sopenharmony_ci/**
2182987da915Sopenharmony_ci * ntfs_dump_attr_property_set()
2183987da915Sopenharmony_ci *
2184987da915Sopenharmony_ci * dump the property_set attribute
2185987da915Sopenharmony_ci */
2186987da915Sopenharmony_cistatic void ntfs_dump_attr_property_set(ATTR_RECORD *attr __attribute__((unused)))
2187987da915Sopenharmony_ci{
2188987da915Sopenharmony_ci	/* TODO */
2189987da915Sopenharmony_ci}
2190987da915Sopenharmony_ci
2191987da915Sopenharmony_cistatic void ntfs_hex_dump(void *buf,unsigned int length);
2192987da915Sopenharmony_ci
2193987da915Sopenharmony_ci/**
2194987da915Sopenharmony_ci * ntfs_dump_attr_logged_utility_stream()
2195987da915Sopenharmony_ci *
2196987da915Sopenharmony_ci * dump the property_set attribute
2197987da915Sopenharmony_ci */
2198987da915Sopenharmony_cistatic void ntfs_dump_attr_logged_utility_stream(ATTR_RECORD *attr,
2199987da915Sopenharmony_ci		ntfs_inode *ni)
2200987da915Sopenharmony_ci{
2201987da915Sopenharmony_ci	char *buf;
2202987da915Sopenharmony_ci	s64 size;
2203987da915Sopenharmony_ci
2204987da915Sopenharmony_ci	if (!opts.verbose)
2205987da915Sopenharmony_ci		return;
2206987da915Sopenharmony_ci	buf = ntfs_attr_readall(ni, AT_LOGGED_UTILITY_STREAM,
2207987da915Sopenharmony_ci			ntfs_attr_get_name(attr), attr->name_length, &size);
2208987da915Sopenharmony_ci	if (buf)
2209987da915Sopenharmony_ci		ntfs_hex_dump(buf, size);
2210987da915Sopenharmony_ci	free(buf);
2211987da915Sopenharmony_ci	/* TODO */
2212987da915Sopenharmony_ci}
2213987da915Sopenharmony_ci
2214987da915Sopenharmony_ci/**
2215987da915Sopenharmony_ci * ntfs_hex_dump
2216987da915Sopenharmony_ci */
2217987da915Sopenharmony_cistatic void ntfs_hex_dump(void *buf,unsigned int length)
2218987da915Sopenharmony_ci{
2219987da915Sopenharmony_ci	unsigned int i=0;
2220987da915Sopenharmony_ci	while (i<length) {
2221987da915Sopenharmony_ci		unsigned int j;
2222987da915Sopenharmony_ci
2223987da915Sopenharmony_ci		/* line start */
2224987da915Sopenharmony_ci		printf("\t%04X  ",i);
2225987da915Sopenharmony_ci
2226987da915Sopenharmony_ci		/* hex content */
2227987da915Sopenharmony_ci		for (j=i;(j<length) && (j<i+16);j++) {
2228987da915Sopenharmony_ci			unsigned char c = *((char *)buf + j);
2229987da915Sopenharmony_ci			printf("%02hhX ",c);
2230987da915Sopenharmony_ci		}
2231987da915Sopenharmony_ci
2232987da915Sopenharmony_ci		/* realign */
2233987da915Sopenharmony_ci		for (;j<i+16;j++) {
2234987da915Sopenharmony_ci			printf("   ");
2235987da915Sopenharmony_ci		}
2236987da915Sopenharmony_ci
2237987da915Sopenharmony_ci		/* char content */
2238987da915Sopenharmony_ci		for (j=i;(j<length) && (j<i+16);j++) {
2239987da915Sopenharmony_ci			unsigned char c = *((char *)buf + j);
2240987da915Sopenharmony_ci			/* display unprintable chars as '.' */
2241987da915Sopenharmony_ci			if ((c<32) || (c>126)) {
2242987da915Sopenharmony_ci				c = '.';
2243987da915Sopenharmony_ci			}
2244987da915Sopenharmony_ci			printf("%c",c);
2245987da915Sopenharmony_ci		}
2246987da915Sopenharmony_ci
2247987da915Sopenharmony_ci		/* end line */
2248987da915Sopenharmony_ci		printf("\n");
2249987da915Sopenharmony_ci		i=j;
2250987da915Sopenharmony_ci	}
2251987da915Sopenharmony_ci}
2252987da915Sopenharmony_ci
2253987da915Sopenharmony_ci/**
2254987da915Sopenharmony_ci * ntfs_dump_attr_unknown
2255987da915Sopenharmony_ci */
2256987da915Sopenharmony_cistatic void ntfs_dump_attr_unknown(ATTR_RECORD *attr)
2257987da915Sopenharmony_ci{
2258987da915Sopenharmony_ci	printf("=====  Please report this unknown attribute type to %s =====\n",
2259987da915Sopenharmony_ci	       NTFS_DEV_LIST);
2260987da915Sopenharmony_ci
2261987da915Sopenharmony_ci	if (!attr->non_resident) {
2262987da915Sopenharmony_ci		/* hex dump */
2263987da915Sopenharmony_ci		printf("\tDumping some of the attribute data:\n");
2264987da915Sopenharmony_ci		ntfs_hex_dump((u8*)attr + le16_to_cpu(attr->value_offset),
2265987da915Sopenharmony_ci				(le32_to_cpu(attr->value_length) > 128) ?
2266987da915Sopenharmony_ci				128 : le32_to_cpu(attr->value_length));
2267987da915Sopenharmony_ci	}
2268987da915Sopenharmony_ci}
2269987da915Sopenharmony_ci
2270987da915Sopenharmony_ci/**
2271987da915Sopenharmony_ci * ntfs_dump_inode_general_info
2272987da915Sopenharmony_ci */
2273987da915Sopenharmony_cistatic void ntfs_dump_inode_general_info(ntfs_inode *inode)
2274987da915Sopenharmony_ci{
2275987da915Sopenharmony_ci	MFT_RECORD *mrec = inode->mrec;
2276987da915Sopenharmony_ci	le16 inode_flags  = mrec->flags;
2277987da915Sopenharmony_ci
2278987da915Sopenharmony_ci	printf("Dumping Inode %llu (0x%llx)\n",
2279987da915Sopenharmony_ci			(long long)inode->mft_no,
2280987da915Sopenharmony_ci			(unsigned long long)inode->mft_no);
2281987da915Sopenharmony_ci
2282987da915Sopenharmony_ci	ntfs_dump_usa_lsn("", mrec);
2283987da915Sopenharmony_ci	printf("MFT Record Seq. Numb.:\t %u (0x%x)\n",
2284987da915Sopenharmony_ci			(unsigned)le16_to_cpu(mrec->sequence_number),
2285987da915Sopenharmony_ci			(unsigned)le16_to_cpu(mrec->sequence_number));
2286987da915Sopenharmony_ci	printf("Number of Hard Links:\t %u (0x%x)\n",
2287987da915Sopenharmony_ci			(unsigned)le16_to_cpu(mrec->link_count),
2288987da915Sopenharmony_ci			(unsigned)le16_to_cpu(mrec->link_count));
2289987da915Sopenharmony_ci	printf("Attribute Offset:\t %u (0x%x)\n",
2290987da915Sopenharmony_ci			(unsigned)le16_to_cpu(mrec->attrs_offset),
2291987da915Sopenharmony_ci			(unsigned)le16_to_cpu(mrec->attrs_offset));
2292987da915Sopenharmony_ci
2293987da915Sopenharmony_ci	printf("MFT Record Flags:\t ");
2294987da915Sopenharmony_ci	if (inode_flags) {
2295987da915Sopenharmony_ci		if (MFT_RECORD_IN_USE & inode_flags) {
2296987da915Sopenharmony_ci			printf("IN_USE ");
2297987da915Sopenharmony_ci			inode_flags &= ~MFT_RECORD_IN_USE;
2298987da915Sopenharmony_ci		}
2299987da915Sopenharmony_ci		if (MFT_RECORD_IS_DIRECTORY & inode_flags) {
2300987da915Sopenharmony_ci			printf("DIRECTORY ");
2301987da915Sopenharmony_ci			inode_flags &= ~MFT_RECORD_IS_DIRECTORY;
2302987da915Sopenharmony_ci		}
2303987da915Sopenharmony_ci		/* The meaning of IS_4 is illusive but not its existence. */
2304987da915Sopenharmony_ci		if (MFT_RECORD_IS_4 & inode_flags) {
2305987da915Sopenharmony_ci			printf("IS_4 ");
2306987da915Sopenharmony_ci			inode_flags &= ~MFT_RECORD_IS_4;
2307987da915Sopenharmony_ci		}
2308987da915Sopenharmony_ci		if (MFT_RECORD_IS_VIEW_INDEX & inode_flags) {
2309987da915Sopenharmony_ci			printf("VIEW_INDEX ");
2310987da915Sopenharmony_ci			inode_flags &= ~MFT_RECORD_IS_VIEW_INDEX;
2311987da915Sopenharmony_ci		}
2312987da915Sopenharmony_ci		if (inode_flags)
2313987da915Sopenharmony_ci			printf("UNKNOWN: 0x%04x", (unsigned)le16_to_cpu(
2314987da915Sopenharmony_ci						inode_flags));
2315987da915Sopenharmony_ci	} else {
2316987da915Sopenharmony_ci		printf("none");
2317987da915Sopenharmony_ci	}
2318987da915Sopenharmony_ci	printf("\n");
2319987da915Sopenharmony_ci
2320987da915Sopenharmony_ci	printf("Bytes Used:\t\t %u (0x%x) bytes\n",
2321987da915Sopenharmony_ci			(unsigned)le32_to_cpu(mrec->bytes_in_use),
2322987da915Sopenharmony_ci			(unsigned)le32_to_cpu(mrec->bytes_in_use));
2323987da915Sopenharmony_ci	printf("Bytes Allocated:\t %u (0x%x) bytes\n",
2324987da915Sopenharmony_ci			(unsigned)le32_to_cpu(mrec->bytes_allocated),
2325987da915Sopenharmony_ci			(unsigned)le32_to_cpu(mrec->bytes_allocated));
2326987da915Sopenharmony_ci
2327987da915Sopenharmony_ci	if (mrec->base_mft_record) {
2328987da915Sopenharmony_ci		printf("Base MFT Record:\t %llu (0x%llx)\n",
2329987da915Sopenharmony_ci				(unsigned long long)
2330987da915Sopenharmony_ci				MREF_LE(mrec->base_mft_record),
2331987da915Sopenharmony_ci				(unsigned long long)
2332987da915Sopenharmony_ci				MREF_LE(mrec->base_mft_record));
2333987da915Sopenharmony_ci	}
2334987da915Sopenharmony_ci	printf("Next Attribute Instance: %u (0x%x)\n",
2335987da915Sopenharmony_ci			(unsigned)le16_to_cpu(mrec->next_attr_instance),
2336987da915Sopenharmony_ci			(unsigned)le16_to_cpu(mrec->next_attr_instance));
2337987da915Sopenharmony_ci
2338987da915Sopenharmony_ci	printf("MFT Padding:\t");
2339987da915Sopenharmony_ci	ntfs_dump_bytes((u8 *)mrec, le16_to_cpu(mrec->usa_ofs) +
2340987da915Sopenharmony_ci			2 * le16_to_cpu(mrec->usa_count),
2341987da915Sopenharmony_ci			le16_to_cpu(mrec->attrs_offset));
2342987da915Sopenharmony_ci	printf("\n");
2343987da915Sopenharmony_ci}
2344987da915Sopenharmony_ci
2345987da915Sopenharmony_ci/**
2346987da915Sopenharmony_ci * ntfs_get_file_attributes
2347987da915Sopenharmony_ci */
2348987da915Sopenharmony_cistatic void ntfs_dump_file_attributes(ntfs_inode *inode)
2349987da915Sopenharmony_ci{
2350987da915Sopenharmony_ci	struct RUNCOUNT runcount;
2351987da915Sopenharmony_ci	ntfs_attr_search_ctx *ctx = NULL;
2352987da915Sopenharmony_ci
2353987da915Sopenharmony_ci	runcount.runs = 0;
2354987da915Sopenharmony_ci	runcount.fragments = 0;
2355987da915Sopenharmony_ci	/* then start enumerating attributes
2356987da915Sopenharmony_ci	   see ntfs_attr_lookup documentation for detailed explanation */
2357987da915Sopenharmony_ci	ctx = ntfs_attr_get_search_ctx(inode, NULL);
2358987da915Sopenharmony_ci	while (!ntfs_attr_lookup(AT_UNUSED, NULL, 0, CASE_SENSITIVE,
2359987da915Sopenharmony_ci			0, NULL, 0, ctx)) {
2360987da915Sopenharmony_ci		if (ctx->attr->type == AT_END || ctx->attr->type == AT_UNUSED) {
2361987da915Sopenharmony_ci			printf("Weird: %s attribute type was found, please "
2362987da915Sopenharmony_ci					"report this.\n",
2363987da915Sopenharmony_ci					get_attribute_type_name(
2364987da915Sopenharmony_ci					ctx->attr->type));
2365987da915Sopenharmony_ci			continue;
2366987da915Sopenharmony_ci		}
2367987da915Sopenharmony_ci
2368987da915Sopenharmony_ci		ntfs_dump_attribute_header(ctx, inode->vol, &runcount);
2369987da915Sopenharmony_ci
2370987da915Sopenharmony_ci		switch (ctx->attr->type) {
2371987da915Sopenharmony_ci		case AT_STANDARD_INFORMATION:
2372987da915Sopenharmony_ci			ntfs_dump_attr_standard_information(ctx->attr);
2373987da915Sopenharmony_ci			break;
2374987da915Sopenharmony_ci		case AT_ATTRIBUTE_LIST:
2375987da915Sopenharmony_ci			ntfs_dump_attr_list(ctx->attr, inode->vol);
2376987da915Sopenharmony_ci			break;
2377987da915Sopenharmony_ci		case AT_FILE_NAME:
2378987da915Sopenharmony_ci			ntfs_dump_attr_file_name(ctx->attr);
2379987da915Sopenharmony_ci			break;
2380987da915Sopenharmony_ci		case AT_OBJECT_ID:
2381987da915Sopenharmony_ci			ntfs_dump_attr_object_id(ctx->attr, inode->vol);
2382987da915Sopenharmony_ci			break;
2383987da915Sopenharmony_ci		case AT_SECURITY_DESCRIPTOR:
2384987da915Sopenharmony_ci			ntfs_dump_attr_security_descriptor(ctx->attr,
2385987da915Sopenharmony_ci					inode->vol);
2386987da915Sopenharmony_ci			break;
2387987da915Sopenharmony_ci		case AT_VOLUME_NAME:
2388987da915Sopenharmony_ci			ntfs_dump_attr_volume_name(ctx->attr);
2389987da915Sopenharmony_ci			break;
2390987da915Sopenharmony_ci		case AT_VOLUME_INFORMATION:
2391987da915Sopenharmony_ci			ntfs_dump_attr_volume_information(ctx->attr);
2392987da915Sopenharmony_ci			break;
2393987da915Sopenharmony_ci		case AT_DATA:
2394987da915Sopenharmony_ci			ntfs_dump_attr_data(ctx->attr, inode);
2395987da915Sopenharmony_ci			break;
2396987da915Sopenharmony_ci		case AT_INDEX_ROOT:
2397987da915Sopenharmony_ci			ntfs_dump_attr_index_root(ctx->attr, inode);
2398987da915Sopenharmony_ci			break;
2399987da915Sopenharmony_ci		case AT_INDEX_ALLOCATION:
2400987da915Sopenharmony_ci			ntfs_dump_attr_index_allocation(ctx->attr, inode);
2401987da915Sopenharmony_ci			break;
2402987da915Sopenharmony_ci		case AT_BITMAP:
2403987da915Sopenharmony_ci			ntfs_dump_attr_bitmap(ctx->attr);
2404987da915Sopenharmony_ci			break;
2405987da915Sopenharmony_ci		case AT_REPARSE_POINT:
2406987da915Sopenharmony_ci			ntfs_dump_attr_reparse_point(ctx->attr, inode);
2407987da915Sopenharmony_ci			break;
2408987da915Sopenharmony_ci		case AT_EA_INFORMATION:
2409987da915Sopenharmony_ci			ntfs_dump_attr_ea_information(ctx->attr);
2410987da915Sopenharmony_ci			break;
2411987da915Sopenharmony_ci		case AT_EA:
2412987da915Sopenharmony_ci			ntfs_dump_attr_ea(ctx->attr, inode->vol);
2413987da915Sopenharmony_ci			break;
2414987da915Sopenharmony_ci		case AT_PROPERTY_SET:
2415987da915Sopenharmony_ci			ntfs_dump_attr_property_set(ctx->attr);
2416987da915Sopenharmony_ci			break;
2417987da915Sopenharmony_ci		case AT_LOGGED_UTILITY_STREAM:
2418987da915Sopenharmony_ci			ntfs_dump_attr_logged_utility_stream(ctx->attr, inode);
2419987da915Sopenharmony_ci			break;
2420987da915Sopenharmony_ci		default:
2421987da915Sopenharmony_ci			ntfs_dump_attr_unknown(ctx->attr);
2422987da915Sopenharmony_ci		}
2423987da915Sopenharmony_ci	}
2424987da915Sopenharmony_ci
2425987da915Sopenharmony_ci	/* if we exited the loop before we're done - notify the user */
2426987da915Sopenharmony_ci	if (errno != ENOENT) {
2427987da915Sopenharmony_ci		ntfs_log_perror("ntfsinfo error: stopped before finished "
2428987da915Sopenharmony_ci				"enumerating attributes");
2429987da915Sopenharmony_ci	} else {
2430987da915Sopenharmony_ci		printf("End of inode reached\n");
2431987da915Sopenharmony_ci		if (opts.verbose) {
2432987da915Sopenharmony_ci			printf("Total runs: %lu (fragments: %lu)\n",
2433987da915Sopenharmony_ci					runcount.runs, runcount.fragments);
2434987da915Sopenharmony_ci		}
2435987da915Sopenharmony_ci	}
2436987da915Sopenharmony_ci
2437987da915Sopenharmony_ci	/* close all data-structures we used */
2438987da915Sopenharmony_ci	ntfs_attr_put_search_ctx(ctx);
2439987da915Sopenharmony_ci	ntfs_inode_close(inode);
2440987da915Sopenharmony_ci}
2441987da915Sopenharmony_ci
2442987da915Sopenharmony_ci/**
2443987da915Sopenharmony_ci * main() - Begin here
2444987da915Sopenharmony_ci *
2445987da915Sopenharmony_ci * Start from here.
2446987da915Sopenharmony_ci *
2447987da915Sopenharmony_ci * Return:  0  Success, the program worked
2448987da915Sopenharmony_ci *	    1  Error, something went wrong
2449987da915Sopenharmony_ci */
2450987da915Sopenharmony_ciint main(int argc, char **argv)
2451987da915Sopenharmony_ci{
2452987da915Sopenharmony_ci	ntfs_volume *vol;
2453987da915Sopenharmony_ci	int res;
2454987da915Sopenharmony_ci
2455987da915Sopenharmony_ci	setlinebuf(stdout);
2456987da915Sopenharmony_ci
2457987da915Sopenharmony_ci	ntfs_log_set_handler(ntfs_log_handler_outerr);
2458987da915Sopenharmony_ci
2459987da915Sopenharmony_ci	res = parse_options(argc, argv);
2460987da915Sopenharmony_ci	if (res > 0)
2461987da915Sopenharmony_ci		printf("Failed to parse command line options\n");
2462987da915Sopenharmony_ci	if (res >= 0)
2463987da915Sopenharmony_ci		exit(res);
2464987da915Sopenharmony_ci
2465987da915Sopenharmony_ci	utils_set_locale();
2466987da915Sopenharmony_ci
2467987da915Sopenharmony_ci	vol = utils_mount_volume(opts.device, NTFS_MNT_RDONLY |
2468987da915Sopenharmony_ci			(opts.force ? NTFS_MNT_RECOVER : 0));
2469987da915Sopenharmony_ci	if (!vol) {
2470987da915Sopenharmony_ci		printf("Failed to open '%s'.\n", opts.device);
2471987da915Sopenharmony_ci		exit(1);
2472987da915Sopenharmony_ci	}
2473987da915Sopenharmony_ci
2474987da915Sopenharmony_ci	/*
2475987da915Sopenharmony_ci	 * if opts.mft is not 0, then we will print out information about
2476987da915Sopenharmony_ci	 * the volume, such as the sector size and whatnot.
2477987da915Sopenharmony_ci	 */
2478987da915Sopenharmony_ci	if (opts.mft)
2479987da915Sopenharmony_ci		ntfs_dump_volume(vol);
2480987da915Sopenharmony_ci
2481987da915Sopenharmony_ci	if ((opts.inode != -1) || opts.filename) {
2482987da915Sopenharmony_ci		ntfs_inode *inode;
2483987da915Sopenharmony_ci		/* obtain the inode */
2484987da915Sopenharmony_ci		if (opts.filename) {
2485987da915Sopenharmony_ci#ifdef HAVE_WINDOWS_H
2486987da915Sopenharmony_ci			char *unix_name;
2487987da915Sopenharmony_ci
2488987da915Sopenharmony_ci			unix_name = ntfs_utils_unix_path(opts.filename);
2489987da915Sopenharmony_ci			if (unix_name) {
2490987da915Sopenharmony_ci				inode = ntfs_pathname_to_inode(vol, NULL,
2491987da915Sopenharmony_ci						unix_name);
2492987da915Sopenharmony_ci				free(unix_name);
2493987da915Sopenharmony_ci			} else
2494987da915Sopenharmony_ci				inode = (ntfs_inode*)NULL;
2495987da915Sopenharmony_ci#else
2496987da915Sopenharmony_ci			inode = ntfs_pathname_to_inode(vol, NULL,
2497987da915Sopenharmony_ci					opts.filename);
2498987da915Sopenharmony_ci#endif
2499987da915Sopenharmony_ci		} else {
2500987da915Sopenharmony_ci			inode = ntfs_inode_open(vol, MK_MREF(opts.inode, 0));
2501987da915Sopenharmony_ci		}
2502987da915Sopenharmony_ci
2503987da915Sopenharmony_ci		/* dump the inode information */
2504987da915Sopenharmony_ci		if (inode) {
2505987da915Sopenharmony_ci			/* general info about the inode's mft record */
2506987da915Sopenharmony_ci			ntfs_dump_inode_general_info(inode);
2507987da915Sopenharmony_ci			/* dump attributes */
2508987da915Sopenharmony_ci			ntfs_dump_file_attributes(inode);
2509987da915Sopenharmony_ci		} else {
2510987da915Sopenharmony_ci			/* can't open inode */
2511987da915Sopenharmony_ci			/*
2512987da915Sopenharmony_ci			 * note: when the specified inode does not exist, either
2513987da915Sopenharmony_ci			 * EIO or or ESPIPE is returned, we should notify better
2514987da915Sopenharmony_ci			 * in those cases
2515987da915Sopenharmony_ci			 */
2516987da915Sopenharmony_ci			ntfs_log_perror("Error loading node");
2517987da915Sopenharmony_ci		}
2518987da915Sopenharmony_ci	}
2519987da915Sopenharmony_ci
2520987da915Sopenharmony_ci	ntfs_umount(vol, FALSE);
2521987da915Sopenharmony_ci	return 0;
2522987da915Sopenharmony_ci}
2523987da915Sopenharmony_ci
2524