no changes

2003/11/02 23:22:27+00:00 flatcap.org!ntfs
move cluster_find to separate source module
implement last option

2003/10/29 10:25:42+00:00 flatcap.org!ntfs
display cluster info about a file / inode

(Logical change 1.299)
edge.strict_endians
flatcap.org!ntfs 2004-03-06 17:42:28 +00:00
parent 100d6d7deb
commit e4f970bfc1
1 changed files with 134 additions and 126 deletions

View File

@ -27,6 +27,7 @@
#include <getopt.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include "ntfscluster.h"
#include "types.h"
@ -35,6 +36,7 @@
#include "volume.h"
#include "debug.h"
#include "dir.h"
#include "cluster.h"
static const char *EXEC_NAME = "ntfscluster";
static struct options opts;
@ -54,8 +56,7 @@ void version (void)
{
printf ("\n%s v%s - Find the owner of any given sector or cluster.\n\n",
EXEC_NAME, VERSION);
printf ("Copyright (c)\n");
printf (" 2002-2003 Richard Russon\n");
printf ("Copyright (c) 2002-2003 Richard Russon\n");
printf ("\n%s\n%s%s\n", ntfs_gpl, ntfs_bugs, ntfs_home);
}
@ -70,8 +71,11 @@ void usage (void)
{
printf ("\nUsage: %s [options] device\n"
" -i --info Print information about the volume (default)\n"
"\n"
" -c range --cluster range Look for objects in this range of clusters\n"
" -s range --sector range Look for objects in this range of sectors\n"
" -I num --inode num Show information about this inode\n"
" -F name --filename name Show information about this file\n"
/* " -l --last Find the last file on the volume\n" */
"\n"
" -f --force Use less caution\n"
@ -94,13 +98,15 @@ void usage (void)
*/
int parse_options (int argc, char **argv)
{
static const char *sopt = "-c:fh?iqs:vV"; // l
static const char *sopt = "-c:F:fh?I:ilqs:vV";
static const struct option lopt[] = {
{ "cluster", required_argument, NULL, 'c' },
{ "filename", required_argument, NULL, 'F' },
{ "force", no_argument, NULL, 'f' },
{ "help", no_argument, NULL, 'h' },
{ "info", no_argument, NULL, 'i' },
//{ "last", no_argument, NULL, 'l' },
{ "inode", required_argument, NULL, 'I' },
{ "last", no_argument, NULL, 'l' },
{ "quiet", no_argument, NULL, 'q' },
{ "sector", required_argument, NULL, 's' },
{ "verbose", no_argument, NULL, 'v' },
@ -112,6 +118,7 @@ int parse_options (int argc, char **argv)
int err = 0;
int ver = 0;
int help = 0;
char *end = NULL;
opterr = 0; /* We'll handle the errors, thank you. */
@ -137,6 +144,14 @@ int parse_options (int argc, char **argv)
else
opts.action = act_error;
break;
case 'F':
if (opts.action == act_none) {
opts.action = act_file;
opts.filename = optarg;
} else {
opts.action = act_error;
}
break;
case 'f':
opts.force++;
break;
@ -144,22 +159,28 @@ int parse_options (int argc, char **argv)
case '?':
help++;
break;
case 'i':
case 'I':
if (opts.action == act_none) {
opts.action = act_info;
opts.action = act_inode;
opts.inode = strtol (optarg, &end, 0);
if (end && *end)
err++;
} else {
opts.action = act_error;
err++;
}
break;
/*
case 'i':
if (opts.action == act_none)
opts.action = act_info;
else
opts.action = act_error;
break;
case 'l':
if (opts.action == act_none)
opts.action = act_last;
else
opts.action = act_error;
break;
*/
case 'q':
opts.quiet++;
break;
@ -206,8 +227,7 @@ int parse_options (int argc, char **argv)
}
if (opts.action == act_error) {
//Eprintf ("You may only specify one action: --info, --cluster, --sector or --last.\n");
Eprintf ("You may only specify one action: --info, --cluster or --sector.\n");
Eprintf ("You may only specify one action: --info, --cluster, --sector or --last.\n");
err++;
} else if (opts.range_begin > opts.range_end) {
Eprintf ("The range must be in ascending order.\n");
@ -333,128 +353,88 @@ int info (ntfs_volume *vol)
}
/**
* cluster_find
* dump_file
*/
int cluster_find (ntfs_volume *vol, LCN s_begin, LCN s_end)
int dump_file (ntfs_volume *vol, ntfs_inode *ino)
{
u64 i;
int in_use = 0, result = 1;
u8 *buffer;
u8 buffer[1024];
ntfs_attr_search_ctx *ctx;
ATTR_RECORD *rec;
int i;
runlist *runs;
if (!vol)
return 1;
utils_inode_get_name (ino, buffer, sizeof (buffer));
buffer = malloc (vol->mft_record_size);
if (!buffer) {
Eprintf ("Couldn't allocate memory.\n");
return 1;
}
printf ("Dump: %s\n", buffer);
for (i = s_begin; (LCN)i < s_end; i++) {
if (utils_cluster_in_use (vol, i) == 1) {
in_use = 1;
break;
}
}
ctx = ntfs_attr_get_search_ctx (ino, NULL);
if (!in_use) {
if (s_begin == s_end)
printf ("cluster isn't in use\n");
else
printf ("clusters aren't in use\n");
result = 0;
goto free;
}
// first, is the cluster in use in $Bitmap?
for (i = 0; (s64)i < vol->nr_mft_records; i++) {
ntfs_inode *inode;
ntfs_attr_search_ctx *ctx;
if (!utils_mftrec_in_use (vol, i)) {
//printf ("%lld skipped\n", i);
continue;
}
inode = ntfs_inode_open (vol, i);
if (!inode) {
Eprintf ("Can't read inode %lld\n", i);
goto free;
}
if (inode->nr_extents == -1) {
printf ("inode %lld is an extent record\n", i);
goto close;
}
Vprintf ("Inode: %lld\n", i);
ctx = ntfs_attr_get_search_ctx (inode, NULL);
if (ntfs_attr_lookup (AT_STANDARD_INFORMATION, NULL, 0, IGNORE_CASE, 0, NULL, 0, ctx) < 0) {
//printf ("extent inode\n");
continue;
}
ntfs_attr_reinit_search_ctx (ctx);
//printf ("Searching for cluster range %lld-%lld\n", s_begin, s_end);
while (ntfs_attr_lookup (AT_UNUSED, NULL, 0, IGNORE_CASE, 0, NULL, 0, ctx) >= 0) {
runlist_element *runs;
int j;
if (!ctx->attr->non_resident) {
//printf ("0x%02X ", ctx->attr->type);
continue;
}
runs = ntfs_mapping_pairs_decompress (vol, ctx->attr, NULL);
if (!runs) {
Eprintf ("Couldn't read the data runs.\n");
ntfs_inode_close (inode);
goto free;
}
Vprintf ("\t[0x%02X]\n", ctx->attr->type);
Vprintf ("\t\tVCN\tLCN\tLength\n");
for (j = 0; runs[j].length > 0; j++) {
LCN a_begin = runs[j].lcn;
LCN a_end = a_begin + runs[j].length - 1;
if (a_begin < 0)
continue; // sparse, discontiguous, etc
Vprintf ("\t\t%lld\t%lld-%lld (%lld)\n", runs[j].vcn, runs[j].lcn, runs[j].lcn + runs[j].length - 1, runs[j].length);
//Vprintf ("\t\t%lld\t%lld\t%lld\n", runs[j].vcn, runs[j].lcn, runs[j].length);
//dprint list
if ((a_begin > s_end) || (a_end < s_begin))
continue; // before or after search range
{
char buffer[256];
utils_inode_get_name (inode, buffer, sizeof (buffer));
//XXX distinguish between file/dir
printf ("inode %lld %s", i, buffer);
utils_attr_get_name (vol, ctx->attr, buffer, sizeof (buffer));
printf ("%c%s\n", PATH_SEP, buffer);
while ((rec = find_attribute (AT_UNUSED, ctx))) {
printf (" 0x%02x - ", rec->type);
if (rec->non_resident) {
printf ("non-resident\n");
runs = ntfs_mapping_pairs_decompress (vol, rec, NULL);
if (runs) {
printf (" VCN LCN Length\n");
for (i = 0; runs[i].length > 0; i++) {
printf (" %8lld %8lld %8lld\n", runs[i].vcn, runs[i].lcn, runs[i].length);
}
break; // XXX if verbose, we should list all matching runs
free (runs);
}
} else {
printf ("resident\n");
}
ntfs_attr_put_search_ctx (ctx);
ctx = NULL;
close:
//printf ("\n");
ntfs_inode_close (inode);
}
free:
free (buffer);
result = 0;
return result;
ntfs_attr_put_search_ctx (ctx);
return 0;
}
/**
* print_match
*/
int print_match (ntfs_inode *ino, ATTR_RECORD *attr, runlist_element *run, void *data)
{
char *buffer;
if (!ino || !attr || !run)
return 1;
buffer = malloc (MAX_PATH);
if (!buffer) {
Eprintf ("!buffer\n");
return 1;
}
utils_inode_get_name (ino, buffer, MAX_PATH);
printf ("Inode %lld %s", ino->mft_no, buffer);
utils_attr_get_name (ino->vol, attr, buffer, MAX_PATH);
printf ("/%s\n", buffer);
free (buffer);
return 0;
}
/**
* find_last
*/
int find_last (ntfs_inode *ino, ATTR_RECORD *attr, runlist_element *run, void *data)
{
struct match *m;
if (!ino || !attr || !run || !data)
return 1;
m = data;
if ((run->lcn + run->length) > m->lcn) {
m->inum = ino->mft_no;
m->lcn = run->lcn + run->length;
}
return 0;
}
/**
* main - Begin here
@ -467,6 +447,8 @@ free:
int main (int argc, char *argv[])
{
ntfs_volume *vol;
ntfs_inode *ino = NULL;
struct match m;
int result = 1;
if (!parse_options (argc, argv))
@ -487,20 +469,46 @@ int main (int argc, char *argv[])
/* Convert to clusters */
opts.range_begin >>= (vol->cluster_size_bits - vol->sector_size_bits);
opts.range_end >>= (vol->cluster_size_bits - vol->sector_size_bits);
result = cluster_find (vol, opts.range_begin, opts.range_end);
result = cluster_find (vol, opts.range_begin, opts.range_end, (cluster_cb*)&print_match, NULL);
break;
case act_cluster:
if (opts.range_begin == opts.range_end)
Qprintf ("Searching for cluster %lld\n", opts.range_begin);
else
Qprintf ("Searching for cluster range %lld-%lld\n", opts.range_begin, opts.range_end);
result = cluster_find (vol, opts.range_begin, opts.range_end);
result = cluster_find (vol, opts.range_begin, opts.range_end, (cluster_cb*)&print_match, NULL);
break;
case act_file:
ino = utils_pathname_to_inode (vol, NULL, opts.filename);
if (ino)
result = dump_file (vol, ino);
break;
case act_inode:
ino = ntfs_inode_open (vol, opts.inode);
if (ino) {
result = dump_file (vol, ino);
ntfs_inode_close (ino);
} else {
Eprintf ("Cannot open inode %lld\n", opts.inode);
}
break;
/*
case act_last:
printf ("Last\n");
memset (&m, 0, sizeof (m));
m.lcn = -1;
result = cluster_find (vol, 0, LONG_MAX, (cluster_cb*)&find_last, &m);
if (m.lcn >= 0) {
ino = ntfs_inode_open (vol, m.inum);
if (ino) {
result = dump_file (vol, ino);
ntfs_inode_close (ino);
} else {
Eprintf ("Cannot open inode %lld\n", opts.inode);
}
result = 0;
} else {
result = 1;
}
break;
*/
case act_info:
default:
result = info (vol);