start to work on the program's behaviour

(Logical change 1.85)
edge.strict_endians
flatcap.org!flatcap 2003-01-10 01:06:19 +00:00
parent 6d5ba60378
commit 7d20cb5376
2 changed files with 83 additions and 220 deletions

View File

@ -25,13 +25,10 @@
#include <stdio.h>
#include <errno.h>
#include <locale.h>
#include <libintl.h>
#include <stdarg.h>
#include <getopt.h>
#include <stdlib.h>
#include <limits.h>
#include <string.h>
#include <stdlib.h>
#include "ntfscluster.h"
#include "types.h"
@ -91,8 +88,9 @@ void usage (void)
{
Iprintf ("Usage: %s [options] device\n"
" -i --info Print information about the volume\n"
" -s range --sector range Look for objects in this range of sectors\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"
" -l --last Find the last file on the volume\n"
"\n"
" -f --force Use less caution\n"
" -q --quiet Less output\n"
@ -103,121 +101,6 @@ void usage (void)
Iprintf ("Please report bugs to: linux-ntfs-dev@lists.sf.net\n\n");
}
/**
* parse_size - Convert a string representing a size
* @value: String to be parsed
* @size: Parsed size
*
* Read a string and convert it to a number. Strings may be suffixed to scale
* them. Any number without a suffix is assumed to be in bytes.
*
* Suffix Description Multiple
* [tT] Terabytes 10^12
* [gG] Gigabytes 10^9
* [mM] Megabytes 10^6
* [kK] Kilobytes 10^3
*
* Notes:
* Only the first character of the suffix is read.
* The multipliers are decimal thousands, not binary: 1000, not 1024.
* If parse_size fails, @size will not be changed
*
* Return: 1 Success
* 0 Error, the string was malformed
*/
int parse_size (const char *value, s64 *size)
{
long long result;
char *suffix = NULL;
if (!value || !size)
return 0;
Dprintf ("Parsing size '%s'.\n", value);
result = strtoll (value, &suffix, 10);
if (result < 0 || errno == ERANGE) {
Eprintf ("Invalid size '%s'.\n", value);
return 0;
}
if (!suffix) {
Eprintf ("Internal error, strtoll didn't return a suffix.\n");
return 0;
}
/*if (strlen (suffix) > 1) {
Eprintf ("Invalid size suffix '%s'. Use T, G, M, or K.\n", suffix);
return 0;
} Can't do this because of ranges*/
switch (suffix[0]) {
case 't': case 'T': result *= 1000;
case 'g': case 'G': result *= 1000;
case 'm': case 'M': result *= 1000;
case 'k': case 'K': result *= 1000;
case '-': case 0:
break;
default:
Eprintf ("Invalid size suffix '%s'. Use T, G, M, or K.\n", suffix);
return 0;
}
Dprintf ("Parsed size = %lld.\n", result);
*size = result;
return 1;
}
/**
* parse_range - Convert a string representing a range of numbers
* @string: The string to be parsed
* @start: The beginning of the range will be stored here
* @finish: The end of the range will be stored here
*
* Read a string of the form n-m. If the lower end is missing, zero will be
* substituted. If the upper end is missing LONG_MAX will be used. If the
* string cannot be parsed correctly, @start and @finish will not be changed.
*
* Return: 1 Success, a valid string was found
* 0 Error, the string was not a valid range
*/
int parse_range (const char *string, s64 *start, s64 *finish)
{
s64 a, b;
char *middle;
if (!string || !start || !finish)
return 0;
middle = strchr (string, '-');
if (string == middle) {
Dprintf ("Range has no beginning, defaulting to 0.\n");
a = 0;
} else {
if (!parse_size (string, &a))
return 0;
}
if (middle) {
if (middle[1] == 0) {
b = LONG_MAX; // XXX ULLONG_MAX
Dprintf ("Range has no end, defaulting to %lld.\n", b);
} else {
if (!parse_size (middle+1, &b))
return 0;
}
} else {
b = a;
}
Dprintf ("Range '%s' = %lld - %lld\n", string, a, b);
*start = a;
*finish = b;
return 1;
}
/**
* parse_options - Read and validate the programs command line
*
@ -229,12 +112,13 @@ int parse_range (const char *string, s64 *start, s64 *finish)
*/
int parse_options (int argc, char **argv)
{
static const char *sopt = "-c:fhiqs:vV";
static const char *sopt = "-c:fhilqs:vV";
static const struct option lopt[] = {
{ "cluster", required_argument, NULL, 'c' },
{ "force", no_argument, NULL, 'f' },
{ "help", no_argument, NULL, 'h' },
{ "info", no_argument, NULL, 'i' },
{ "last", no_argument, NULL, 'l' },
{ "quiet", no_argument, NULL, 'q' },
{ "sector", required_argument, NULL, 's' },
{ "verbose", no_argument, NULL, 'v' },
@ -249,6 +133,10 @@ int parse_options (int argc, char **argv)
opterr = 0; /* We'll handle the errors, thank you. */
opts.action = act_none;
opts.range_begin = -1;
opts.range_end = -1;
while ((c = getopt_long (argc, argv, sopt, lopt, NULL)) != -1) {
switch (c) {
case 1: /* A non-option argument */
@ -261,10 +149,11 @@ int parse_options (int argc, char **argv)
break;
case 'c':
if ((opts.cluster_begin > 0) || (opts.cluster_end > 0) ||
!parse_range (optarg, &opts.cluster_begin, &opts.cluster_end)) {
err++;
}
if ((opts.action == act_none) &&
(utils_parse_range (optarg, &opts.range_begin, &opts.range_end, FALSE)))
opts.action = act_cluster;
else
opts.action = act_error;
break;
case 'f':
opts.force++;
@ -273,16 +162,28 @@ int parse_options (int argc, char **argv)
help++;
break;
case 'i':
opts.info++;
if (opts.action == act_none) {
opts.action = act_info;
} else {
opts.action = act_error;
err++;
}
break;
case 'l':
if (opts.action == act_none)
opts.action = act_last;
else
opts.action = act_error;
break;
case 'q':
opts.quiet++;
break;
case 's':
if ((opts.sector_begin > 0) || (opts.sector_end > 0) ||
!parse_range (optarg, &opts.sector_begin, &opts.sector_end)) {
err++;
}
if ((opts.action == act_none) &&
(utils_parse_range (optarg, &opts.range_begin, &opts.range_end, FALSE)))
opts.action = act_sector;
else
opts.action = act_error;
break;
case 'v':
opts.verbose++;
@ -291,11 +192,10 @@ int parse_options (int argc, char **argv)
ver++;
break;
default:
if ((optopt == 'c') || (optopt == 's')) {
if ((optopt == 'c') || (optopt == 's'))
Eprintf ("Option '%s' requires an argument.\n", argv[optind-1]);
} else {
else
Eprintf ("Unknown option '%s'.\n", argv[optind-1]);
}
err++;
break;
}
@ -304,6 +204,11 @@ int parse_options (int argc, char **argv)
if (help || ver) {
opts.quiet = 0;
} else {
if (opts.action == act_none)
opts.action = act_info;
if (opts.action == act_info)
opts.quiet = 0;
if (opts.device == NULL) {
Eprintf ("You must specify exactly one device.\n");
err++;
@ -314,18 +219,13 @@ int parse_options (int argc, char **argv)
err++;
}
if (opts.sector_end && opts.cluster_end) {
Eprintf ("You must specify either a sector or a cluster.\n");
if (opts.action == act_error) {
Eprintf ("You may only specify one action: --info, --cluster, --sector or --last.\n");
err++;
}
if (opts.cluster_begin > opts.cluster_end) {
Eprintf ("The cluster range must be in ascending order.\n");
} else if (opts.range_begin > opts.range_end) {
Eprintf ("The range must be in ascending order.\n");
err++;
}
if (opts.sector_begin > opts.sector_end) {
Eprintf ("The sector range must be in ascending order.\n");
err++;
}
}
}
if (ver)
@ -405,9 +305,9 @@ int cluster_find (ntfs_volume *vol, LCN s_begin, LCN s_end)
return 1;
}
// first, is the cluster in use in $Bitmap?
for (i = 0; i < vol->nr_mft_records; i++) {
//for (i = 0; i < 30; i++) {
//for (i = 162; i < 175; i++) {
ntfs_inode *inode;
ntfs_attr_search_ctx *ctx;
@ -490,56 +390,6 @@ free:
return result;
}
/**
* my_locale
*/
int my_locale (void)
{
const char *locale;
locale = setlocale (LC_ALL, "");
if (!locale) {
locale = setlocale (LC_ALL, NULL);
Vprintf ("Failed to set locale, using default '%s'.\n", locale);
return 1;
} else {
Vprintf ("Using locale '%s'.\n", locale);
return 0;
}
}
/**
* get_vol
*/
ntfs_volume * get_vol (const char *device, unsigned long flags, BOOL force)
{
ntfs_volume *vol;
if (!device)
return NULL;
if (!valid_device (device, force))
return NULL;
vol = ntfs_mount (device, MS_RDONLY);
if (!vol) {
Eprintf ("Couldn't mount device '%s': %s\n", device, strerror (errno));
return NULL;
}
if (vol->flags & VOLUME_IS_DIRTY) {
Iprintf ("Volume is dirty.\n");
if (!force) {
Eprintf ("Run chkdsk and try again, or use the --force option.\n");
ntfs_umount (vol, FALSE);
return NULL;
}
Iprintf ("Forced to continue.\n");
}
return vol;
}
/**
* main - Begin here
*
@ -551,31 +401,37 @@ ntfs_volume * get_vol (const char *device, unsigned long flags, BOOL force)
int main (int argc, char *argv[])
{
ntfs_volume *vol;
int result;
int result = 1;
if (!parse_options (argc, argv))
return 1;
my_locale();
utils_set_locale();
vol = get_vol (opts.device, MS_RDONLY, opts.force);
vol = utils_mount_volume (opts.device, MS_RDONLY, opts.force);
if (!vol)
return 1;
#if 0
if (opts.info) {
//result = get_info (vol);
} else if (opts.cluster) {
result = cluster_find (vol, opts.cluster);
} else if (opts.sector) {
//result =
} else {
//result =
switch (opts.action) {
case act_sector:
Iprintf ("Searching for sector range %lld-%lld\n", opts.range_begin, opts.range_end);
/* 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);
break;
case act_cluster:
Iprintf ("Searching for cluster range %lld-%lld\n", opts.range_begin, opts.range_end);
result = cluster_find (vol, opts.range_begin, opts.range_end);
break;
case act_last:
printf ("Last\n");
break;
case act_info:
default:
printf ("Info\n");
break;
}
#endif
//opts.cluster_end = LONG_MAX;
printf ("Searching for cluster range %lld-%lld\n", opts.cluster_begin, opts.cluster_end);
result = cluster_find (vol, opts.cluster_begin, opts.cluster_end);
ntfs_umount (vol, FALSE);
return result;

View File

@ -26,16 +26,23 @@
#include "types.h"
enum action {
act_none = 1,
act_info = 2,
act_cluster = 3,
act_sector = 4,
act_last = 5,
act_error = 6,
};
struct options {
char *device; /* Device/File to work with */
int info; /* Show volume info */
int quiet; /* Less output */
int verbose; /* Extra output */
int force; /* Override common sense */
u64 sector_begin; /* Look for objects in this range of sectors */
u64 sector_end;
u64 cluster_begin; /* Look for objects in this range of clusters */
u64 cluster_end;
char *device; /* Device/File to work with */
enum action action; /* What to do */
int quiet; /* Less output */
int verbose; /* Extra output */
int force; /* Override common sense */
u64 range_begin; /* Look for objects in this range */
u64 range_end;
};
#endif /* _NTFSCLUSTER_H_ */