use new logging

edge.strict_endians
flatcap 2005-11-20 14:15:33 +00:00
parent 0f7ee235ed
commit abf0cfba5d
5 changed files with 379 additions and 388 deletions

View File

@ -70,6 +70,7 @@
#include "mst.h"
#include "utils.h"
#include "version.h"
#include "logging.h"
typedef struct {
BOOL is_volume;
@ -87,8 +88,6 @@ typedef struct {
};
} logfile_file;
GEN_PRINTF(Eprintf, stderr, NULL, FALSE)
/**
* logfile_close
*/
@ -98,15 +97,15 @@ static int logfile_close(logfile_file *logfile)
if (logfile->na)
ntfs_attr_close(logfile->na);
if (logfile->ni && ntfs_inode_close(logfile->ni))
Eprintf("Warning: Failed to close $LogFile (inode %i):"
" %s\n", FILE_LogFile, strerror(errno));
ntfs_log_perror("Warning: Failed to close $LogFile "
"(inode %i)", FILE_LogFile);
if (ntfs_umount(logfile->vol, 0))
Eprintf("Warning: Failed to umount %s: %s\n",
logfile->filename, strerror(errno));
ntfs_log_perror("Warning: Failed to umount %s",
logfile->filename);
} else {
if (close(logfile->fd))
Eprintf("Warning: Failed to close file %s: %s\n",
logfile->filename, strerror(errno));
ntfs_log_perror("Warning: Failed to close file %s",
logfile->filename);
}
return 0;
}
@ -130,17 +129,17 @@ static void device_err_exit(ntfs_volume *vol, ntfs_inode *ni,
if (na)
ntfs_attr_close(na);
if (ni && ntfs_inode_close(ni))
Eprintf("Warning: Failed to close $LogFile (inode %i): %s\n",
FILE_LogFile, strerror(errno));
ntfs_log_perror("Warning: Failed to close $LogFile (inode %i)",
FILE_LogFile);
if (ntfs_umount(vol, 0))
Eprintf("Warning: Failed to umount: %s\n", strerror(errno));
ntfs_log_perror("Warning: Failed to umount");
fprintf(stderr, "ERROR: ");
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
va_end(ap);
Eprintf("Aborting...\n");
ntfs_log_error("Aborting...\n");
exit(1);
}
@ -160,7 +159,7 @@ static void log_err_exit(u8 *buf, const char *fmt, ...)
vfprintf(stderr, fmt, ap);
va_end(ap);
Eprintf("Aborting...\n");
ntfs_log_error("Aborting...\n");
exit(1);
}
@ -170,7 +169,7 @@ static void log_err_exit(u8 *buf, const char *fmt, ...)
__attribute__((noreturn))
static void usage(const char *exec_name)
{
Eprintf("%s v%s (libntfs %s) - Interpret and display information "
ntfs_log_error("%s v%s (libntfs %s) - Interpret and display information "
"about the journal\n($LogFile) of an NTFS volume.\n"
"Copyright (c) 2000-2005 Anton Altaparmakov.\n"
"%s is free software, released under the GNU General "
@ -202,7 +201,7 @@ static int logfile_open(BOOL is_volume, const char *filename,
if (!vol)
log_err_exit(NULL, "Failed to mount %s: %s\n",
filename, strerror(errno));
printf("Mounted NTFS volume %s (NTFS v%i.%i) on device %s.\n",
ntfs_log_info("Mounted NTFS volume %s (NTFS v%i.%i) on device %s.\n",
vol->vol_name ? vol->vol_name : "<NO_NAME>",
vol->major_ver, vol->minor_ver, filename);
if (ntfs_version_is_supported(vol))
@ -265,13 +264,13 @@ static int logfile_pread(logfile_file *logfile, int ofs, int count, u8 *buf)
br = (int)ntfs_attr_pread(logfile->na, ofs, count, buf);
} else {
if (lseek(logfile->fd, ofs, SEEK_SET)==-1) {
Eprintf("Could not seek to offset %u\n", ofs);
ntfs_log_error("Could not seek to offset %u\n", ofs);
return 0;
}
br = read(logfile->fd, buf, count);
}
if (br != count) {
Eprintf("Only %d out of %d bytes read starting at %d\n",
ntfs_log_error("Only %d out of %d bytes read starting at %d\n",
br, count, ofs);
}
return br;
@ -340,29 +339,35 @@ static void restart_header_sanity(RESTART_PAGE_HEADER *rstr, u8 *buf)
"yet.\n");
}
/**
* dump_restart_areas_header
*/
static void dump_restart_areas_header(RESTART_PAGE_HEADER *rstr)
{
printf("\nRestart page header:\n");
printf("magic = %s\n", ntfs_is_rstr_record(rstr->magic) ? "RSTR" :
ntfs_log_info("\nRestart page header:\n");
ntfs_log_info("magic = %s\n", ntfs_is_rstr_record(rstr->magic) ? "RSTR" :
"CHKD");
printf("usa_ofs = %u (0x%x)\n", le16_to_cpu(rstr->usa_ofs),
ntfs_log_info("usa_ofs = %u (0x%x)\n", le16_to_cpu(rstr->usa_ofs),
le16_to_cpu(rstr->usa_ofs));
printf("usa_count = %u (0x%x)\n", le16_to_cpu(rstr->usa_count),
ntfs_log_info("usa_count = %u (0x%x)\n", le16_to_cpu(rstr->usa_count),
le16_to_cpu(rstr->usa_count));
printf("chkdsk_lsn = %lli (0x%llx)\n",
ntfs_log_info("chkdsk_lsn = %lli (0x%llx)\n",
(long long)sle64_to_cpu(rstr->chkdsk_lsn),
(unsigned long long)sle64_to_cpu(rstr->chkdsk_lsn));
printf("system_page_size = %u (0x%x)\n",
ntfs_log_info("system_page_size = %u (0x%x)\n",
(unsigned int)le32_to_cpu(rstr->system_page_size),
(unsigned int)le32_to_cpu(rstr->system_page_size));
printf("log_page_size = %u (0x%x)\n",
ntfs_log_info("log_page_size = %u (0x%x)\n",
(unsigned int)le32_to_cpu(rstr->log_page_size),
(unsigned int)le32_to_cpu(rstr->log_page_size));
printf("restart_offset = %u (0x%x)\n",
ntfs_log_info("restart_offset = %u (0x%x)\n",
le16_to_cpu(rstr->restart_area_offset),
le16_to_cpu(rstr->restart_area_offset));
}
/**
* dump_restart_areas_area
*/
static void dump_restart_areas_area(RESTART_PAGE_HEADER *rstr)
{
LOG_CLIENT_RECORD *lcr;
@ -371,40 +376,40 @@ static void dump_restart_areas_area(RESTART_PAGE_HEADER *rstr)
ra = (RESTART_AREA*)((u8*)rstr +
le16_to_cpu(rstr->restart_area_offset));
printf("current_lsn = %lli (0x%llx)\n",
ntfs_log_info("current_lsn = %lli (0x%llx)\n",
(long long)sle64_to_cpu(ra->current_lsn),
(unsigned long long)sle64_to_cpu(ra->current_lsn));
printf("log_clients = %u (0x%x)\n", le16_to_cpu(ra->log_clients),
ntfs_log_info("log_clients = %u (0x%x)\n", le16_to_cpu(ra->log_clients),
le16_to_cpu(ra->log_clients));
printf("client_free_list = %i (0x%x)\n",
ntfs_log_info("client_free_list = %i (0x%x)\n",
(s16)le16_to_cpu(ra->client_free_list),
le16_to_cpu(ra->client_free_list));
printf("client_in_use_list = %i (0x%x)\n",
ntfs_log_info("client_in_use_list = %i (0x%x)\n",
(s16)le16_to_cpu(ra->client_in_use_list),
le16_to_cpu(ra->client_in_use_list));
printf("flags = 0x%.4x\n", le16_to_cpu(ra->flags));
printf("seq_number_bits = %u (0x%x)\n",
ntfs_log_info("flags = 0x%.4x\n", le16_to_cpu(ra->flags));
ntfs_log_info("seq_number_bits = %u (0x%x)\n",
(unsigned int)le32_to_cpu(ra->seq_number_bits),
(unsigned int)le32_to_cpu(ra->seq_number_bits));
printf("restart_area_length = %u (0x%x)\n",
ntfs_log_info("restart_area_length = %u (0x%x)\n",
le16_to_cpu(ra->restart_area_length),
le16_to_cpu(ra->restart_area_length));
printf("client_array_offset = %u (0x%x)\n",
ntfs_log_info("client_array_offset = %u (0x%x)\n",
le16_to_cpu(ra->client_array_offset),
le16_to_cpu(ra->client_array_offset));
printf("file_size = %lli (0x%llx)\n",
ntfs_log_info("file_size = %lli (0x%llx)\n",
(long long)sle64_to_cpu(ra->file_size),
(unsigned long long)sle64_to_cpu(ra->file_size));
printf("last_lsn_data_length = %u (0x%x)\n",
ntfs_log_info("last_lsn_data_length = %u (0x%x)\n",
(unsigned int)le32_to_cpu(ra->last_lsn_data_length),
(unsigned int)le32_to_cpu(ra->last_lsn_data_length));
printf("log_record_header_length = %u (0x%x)\n",
ntfs_log_info("log_record_header_length = %u (0x%x)\n",
le16_to_cpu(ra->log_record_header_length),
le16_to_cpu(ra->log_record_header_length));
printf("log_page_data_offset = %u (0x%x)\n",
ntfs_log_info("log_page_data_offset = %u (0x%x)\n",
le16_to_cpu(ra->log_page_data_offset),
le16_to_cpu(ra->log_page_data_offset));
printf("restart_log_open_count = %u (0x%x)\n",
ntfs_log_info("restart_log_open_count = %u (0x%x)\n",
(unsigned)le32_to_cpu(ra->restart_log_open_count),
(unsigned)le32_to_cpu(ra->restart_log_open_count));
lcr = (LOG_CLIENT_RECORD*)((u8*)ra +
@ -412,24 +417,24 @@ static void dump_restart_areas_area(RESTART_PAGE_HEADER *rstr)
for (client = 0; client < le16_to_cpu(ra->log_clients); client++) {
char *client_name;
printf("\nLog client record number %i:\n", client + 1);
printf("oldest_lsn = %lli (0x%llx)\n",
ntfs_log_info("\nLog client record number %i:\n", client + 1);
ntfs_log_info("oldest_lsn = %lli (0x%llx)\n",
(long long)sle64_to_cpu(lcr->oldest_lsn),
(unsigned long long)
sle64_to_cpu(lcr->oldest_lsn));
printf("client_restart_lsn = %lli (0x%llx)\n", (long long)
ntfs_log_info("client_restart_lsn = %lli (0x%llx)\n", (long long)
sle64_to_cpu(lcr->client_restart_lsn),
(unsigned long long)
sle64_to_cpu(lcr->client_restart_lsn));
printf("prev_client = %i (0x%x)\n",
ntfs_log_info("prev_client = %i (0x%x)\n",
(s16)le16_to_cpu(lcr->prev_client),
le16_to_cpu(lcr->prev_client));
printf("next_client = %i (0x%x)\n",
ntfs_log_info("next_client = %i (0x%x)\n",
(s16)le16_to_cpu(lcr->next_client),
le16_to_cpu(lcr->next_client));
printf("seq_number = %u (0x%x)\n", le16_to_cpu(lcr->seq_number),
ntfs_log_info("seq_number = %u (0x%x)\n", le16_to_cpu(lcr->seq_number),
le16_to_cpu(lcr->seq_number));
printf("client_name_length = %u (0x%x)\n",
ntfs_log_info("client_name_length = %u (0x%x)\n",
(unsigned int)le32_to_cpu(lcr->client_name_length) / 2,
(unsigned int)le32_to_cpu(lcr->client_name_length) / 2);
if (le32_to_cpu(lcr->client_name_length)) {
@ -437,12 +442,12 @@ static void dump_restart_areas_area(RESTART_PAGE_HEADER *rstr)
if (ntfs_ucstombs(lcr->client_name,
le32_to_cpu(lcr->client_name_length) /
2, &client_name, 0) < 0) {
perror("Failed to convert log client name");
ntfs_log_perror("Failed to convert log client name");
client_name = strdup("<conversion error>");
}
} else
client_name = strdup("<unnamed>");
printf("client_name = %s\n", client_name);
ntfs_log_info("client_name = %s\n", client_name);
free(client_name);
/*
* Log client records are fixed size so we can simply use the
@ -473,7 +478,7 @@ rstr_pass_loc:
"detected in restart page header. Cannot "
"handle this yet.\n");
if (pass == 1)
printf("$LogFile version %i.%i.\n",
ntfs_log_info("$LogFile version %i.%i.\n",
sle16_to_cpu(rstr->major_ver),
sle16_to_cpu(rstr->minor_ver));
else /* if (pass == 2) */ {
@ -511,10 +516,10 @@ rstr_pass_loc:
"yet.\n");
}
/* The restart page header is in rstr and it is mst deprotected. */
printf("\n%s restart page:\n", pass == 1 ? "1st" : "2nd");
ntfs_log_info("\n%s restart page:\n", pass == 1 ? "1st" : "2nd");
dump_restart_areas_header(rstr);
printf("\nRestart area:\n");
ntfs_log_info("\nRestart area:\n");
dump_restart_areas_area(rstr);
skip_rstr_pass:
@ -533,55 +538,55 @@ skip_rstr_pass:
static void dump_log_record(LOG_RECORD *lr)
{
unsigned int i;
printf("this lsn = 0x%llx\n",
ntfs_log_info("this lsn = 0x%llx\n",
(unsigned long long)le64_to_cpu(lr->this_lsn));
printf("client previous lsn = 0x%llx\n", (unsigned long long)
ntfs_log_info("client previous lsn = 0x%llx\n", (unsigned long long)
le64_to_cpu(lr->client_previous_lsn));
printf("client undo next lsn = 0x%llx\n", (unsigned long long)
ntfs_log_info("client undo next lsn = 0x%llx\n", (unsigned long long)
le64_to_cpu(lr->client_undo_next_lsn));
printf("client data length = 0x%x\n",
ntfs_log_info("client data length = 0x%x\n",
(unsigned int)le32_to_cpu(lr->client_data_length));
printf("client_id.seq_number = 0x%x\n",
ntfs_log_info("client_id.seq_number = 0x%x\n",
le16_to_cpu(lr->client_id.seq_number));
printf("client_id.client_index = 0x%x\n",
ntfs_log_info("client_id.client_index = 0x%x\n",
le16_to_cpu(lr->client_id.client_index));
printf("record type = 0x%x\n",
ntfs_log_info("record type = 0x%x\n",
(unsigned int)le32_to_cpu(lr->record_type));
printf("transaction_id = 0x%x\n",
ntfs_log_info("transaction_id = 0x%x\n",
(unsigned int)le32_to_cpu(lr->transaction_id));
printf("flags = 0x%x:", lr->flags);
ntfs_log_info("flags = 0x%x:", lr->flags);
if (!lr->flags)
printf(" NONE\n");
ntfs_log_info(" NONE\n");
else {
int _b = 0;
if (lr->flags & LOG_RECORD_MULTI_PAGE) {
printf(" LOG_RECORD_MULTI_PAGE");
ntfs_log_info(" LOG_RECORD_MULTI_PAGE");
_b = 1;
}
if (lr->flags & ~LOG_RECORD_MULTI_PAGE) {
if (_b)
printf(" |");
printf(" Unknown flags");
ntfs_log_info(" |");
ntfs_log_info(" Unknown flags");
}
printf("\n");
ntfs_log_info("\n");
}
printf("redo_operation = 0x%x\n", le16_to_cpu(lr->redo_operation));
printf("undo_operation = 0x%x\n", le16_to_cpu(lr->undo_operation));
printf("redo_offset = 0x%x\n", le16_to_cpu(lr->redo_offset));
printf("redo_length = 0x%x\n", le16_to_cpu(lr->redo_length));
printf("undo_offset = 0x%x\n", le16_to_cpu(lr->undo_offset));
printf("undo_length = 0x%x\n", le16_to_cpu(lr->undo_length));
printf("target_attribute = 0x%x\n", le16_to_cpu(lr->target_attribute));
printf("lcns_to_follow = 0x%x\n", le16_to_cpu(lr->lcns_to_follow));
printf("record_offset = 0x%x\n", le16_to_cpu(lr->record_offset));
printf("attribute_offset = 0x%x\n", le16_to_cpu(lr->attribute_offset));
printf("target_vcn = 0x%llx\n",
ntfs_log_info("redo_operation = 0x%x\n", le16_to_cpu(lr->redo_operation));
ntfs_log_info("undo_operation = 0x%x\n", le16_to_cpu(lr->undo_operation));
ntfs_log_info("redo_offset = 0x%x\n", le16_to_cpu(lr->redo_offset));
ntfs_log_info("redo_length = 0x%x\n", le16_to_cpu(lr->redo_length));
ntfs_log_info("undo_offset = 0x%x\n", le16_to_cpu(lr->undo_offset));
ntfs_log_info("undo_length = 0x%x\n", le16_to_cpu(lr->undo_length));
ntfs_log_info("target_attribute = 0x%x\n", le16_to_cpu(lr->target_attribute));
ntfs_log_info("lcns_to_follow = 0x%x\n", le16_to_cpu(lr->lcns_to_follow));
ntfs_log_info("record_offset = 0x%x\n", le16_to_cpu(lr->record_offset));
ntfs_log_info("attribute_offset = 0x%x\n", le16_to_cpu(lr->attribute_offset));
ntfs_log_info("target_vcn = 0x%llx\n",
(unsigned long long)sle64_to_cpu(lr->target_vcn));
if (le16_to_cpu(lr->lcns_to_follow) > 0)
printf("Array of lcns:\n");
ntfs_log_info("Array of lcns:\n");
for (i = 0; i < le16_to_cpu(lr->lcns_to_follow); i++)
printf("lcn_list[%u].lcn = 0x%llx\n", i, (unsigned long long)
ntfs_log_info("lcn_list[%u].lcn = 0x%llx\n", i, (unsigned long long)
sle64_to_cpu(lr->lcn_list[i].lcn));
}
@ -600,7 +605,7 @@ rcrd_pass_loc:
rcrd = (RECORD_PAGE_HEADER*)((u8*)rcrd + page_size);
if ((u8*)rcrd + page_size > buf + buf_size)
return;
printf("\nLog record page number %i", pass);
ntfs_log_info("\nLog record page number %i", pass);
if (!ntfs_is_rcrd_record(rcrd->magic) &&
!ntfs_is_chkd_record(rcrd->magic)) {
unsigned int i;
@ -616,17 +621,17 @@ rcrd_pass_loc:
} else
puts(":");
/* Dump log record page */
printf("magic = %s\n", ntfs_is_rcrd_record(rcrd->magic) ? "RCRD" :
ntfs_log_info("magic = %s\n", ntfs_is_rcrd_record(rcrd->magic) ? "RCRD" :
"CHKD");
// TODO: I am here... (AIA)
printf("copy.last_lsn/file_offset = 0x%llx\n", (unsigned long long)
ntfs_log_info("copy.last_lsn/file_offset = 0x%llx\n", (unsigned long long)
le64_to_cpu(rcrd->copy.last_lsn));
printf("flags = 0x%x\n", (unsigned int)le32_to_cpu(rcrd->flags));
printf("page count = %i\n", le16_to_cpu(rcrd->page_count));
printf("page position = %i\n", le16_to_cpu(rcrd->page_position));
printf("header.next_record_offset = 0x%llx\n", (unsigned long long)
ntfs_log_info("flags = 0x%x\n", (unsigned int)le32_to_cpu(rcrd->flags));
ntfs_log_info("page count = %i\n", le16_to_cpu(rcrd->page_count));
ntfs_log_info("page position = %i\n", le16_to_cpu(rcrd->page_position));
ntfs_log_info("header.next_record_offset = 0x%llx\n", (unsigned long long)
le64_to_cpu(rcrd->header.packed.next_record_offset));
printf("header.last_end_lsn = 0x%llx\n", (unsigned long long)
ntfs_log_info("header.last_end_lsn = 0x%llx\n", (unsigned long long)
le64_to_cpu(rcrd->header.packed.last_end_lsn));
/*
* Where does the 0x40 come from? Is it just usa_offset +
@ -635,7 +640,7 @@ rcrd_pass_loc:
lr = (LOG_RECORD*)((u8*)rcrd + 0x40);
client = 0;
do {
printf("\nLog record %i:\n", client);
ntfs_log_info("\nLog record %i:\n", client);
dump_log_record(lr);
client++;
lr = (LOG_RECORD*)((u8*)lr + 0x70);
@ -658,7 +663,9 @@ int main(int argc, char **argv)
logfile_file logfile;
u8 *buf;
printf("\n");
ntfs_log_set_handler(ntfs_log_handler_outerr);
ntfs_log_info("\n");
if (argc < 2 || argc > 3)
/* print usage and exit */
usage(argv[0]);
@ -686,14 +693,13 @@ int main(int argc, char **argv)
if (logfile.data_size <= buf_size)
buf_size = logfile.data_size;
else
Eprintf("Warning: $LogFile is too big. "
ntfs_log_error("Warning: $LogFile is too big. "
"Only analysing the first 64MiB.\n");
/* For simplicity we read all of $LogFile/$DATA into memory. */
buf = malloc(buf_size);
if (!buf) {
Eprintf("Failed to allocate buffer for file data: %s\n",
strerror(errno));
ntfs_log_perror("Failed to allocate buffer for file data");
logfile_close(&logfile);
exit(1);
}
@ -743,20 +749,20 @@ int main(int argc, char **argv)
* Second, verify the restart area itself.
*/
// TODO: Implement this.
Eprintf("Warning: Sanity checking of restart area not implemented "
ntfs_log_error("Warning: Sanity checking of restart area not implemented "
"yet.\n");
/*
* Third and last, verify the array of log client records.
*/
// TODO: Implement this.
Eprintf("Warning: Sanity checking of array of log client records not "
ntfs_log_error("Warning: Sanity checking of array of log client records not "
"implemented yet.\n");
/*
* Dump the restart headers & areas.
*/
rcrd = (RECORD_PAGE_HEADER*)dump_restart_areas(rstr, buf, page_size);
printf("\n\nFinished with restart pages. "
ntfs_log_info("\n\nFinished with restart pages. "
"Beginning with log pages.\n");
/*

View File

@ -74,6 +74,7 @@
#include "logfile.h"
#include "utils.h"
#include "version.h"
#include "logging.h"
#ifdef NO_NTFS_DEVICE_DEFAULT_IO_OPS
# error "No default device io operations! Cannot build ntfsfix. \
@ -81,13 +82,9 @@ You need to run ./configure without the --disable-default-device-io-ops \
switch if you want to be able to build the NTFS utilities."
#endif
GEN_PRINTF(Eprintf, stdout, NULL, FALSE)
GEN_PRINTF(Vprintf, stdout, NULL, FALSE)
GEN_PRINTF(Qprintf, stdout, NULL, FALSE)
static const char *EXEC_NAME = "ntfsfix";
static const char *OK = "OK";
static const char *FAILED = "FAILED";
static const char *OK = "OK\n";
static const char *FAILED = "FAILED\n";
static BOOL vol_is_dirty = FALSE;
static BOOL journal_is_empty = FALSE;
@ -95,10 +92,13 @@ struct {
char *volume;
} opt;
/**
* usage
*/
__attribute__((noreturn))
static int usage(void)
{
printf("%s v%s (libntfs %s)\n"
ntfs_log_info("%s v%s (libntfs %s)\n"
"\n"
"Usage: %s [options] device\n"
" Attempt to fix an NTFS partition.\n"
@ -109,28 +109,34 @@ static int usage(void)
"For example: %s /dev/hda6\n\n",
EXEC_NAME, VERSION, ntfs_libntfs_version(), EXEC_NAME,
EXEC_NAME);
printf("%s%s", ntfs_bugs, ntfs_home);
ntfs_log_info("%s%s", ntfs_bugs, ntfs_home);
exit(1);
}
/**
* version
*/
__attribute__((noreturn))
static void version(void)
{
printf("%s v%s\n\n"
ntfs_log_info("%s v%s\n\n"
"Attempt to fix an NTFS partition.\n\n"
"Copyright (c) 2000-2003 Anton Altaparmakov.\n\n",
EXEC_NAME, VERSION);
printf("%s\n%s%s", ntfs_gpl, ntfs_bugs, ntfs_home);
ntfs_log_info("%s\n%s%s", ntfs_gpl, ntfs_bugs, ntfs_home);
exit(1);
}
/**
* parse_options
*/
static void parse_options(int argc, char **argv)
{
char c;
static const char *sopt = "-hV";
static const struct option lopt[] = {
{ "help", no_argument, NULL, 'h' },
{ "version", no_argument, NULL, 'V' },
{ "help", no_argument, NULL, 'h' },
{ "version", no_argument, NULL, 'V' },
{ NULL, 0, NULL, 0 }
};
@ -142,7 +148,7 @@ static void parse_options(int argc, char **argv)
if (!opt.volume)
opt.volume = argv[optind - 1];
else {
printf("ERROR: Too many arguments.\n");
ntfs_log_info("ERROR: Too many arguments.\n");
usage();
}
break;
@ -152,17 +158,20 @@ static void parse_options(int argc, char **argv)
case 'V':
version();
default:
printf("ERROR: Unknown option '%s'.\n", argv[optind - 1]);
ntfs_log_info("ERROR: Unknown option '%s'.\n", argv[optind - 1]);
usage();
}
}
if (opt.volume == NULL) {
printf("ERROR: You must specify a device.\n");
ntfs_log_info("ERROR: You must specify a device.\n");
usage();
}
}
/**
* OLD_ntfs_volume_set_flags
*/
static int OLD_ntfs_volume_set_flags(ntfs_volume *vol, const u16 flags)
{
MFT_RECORD *m = NULL;
@ -233,6 +242,9 @@ err_exit:
return ret;
}
/**
* set_dirty_flag
*/
static int set_dirty_flag(ntfs_volume *vol)
{
u16 flags;
@ -240,7 +252,7 @@ static int set_dirty_flag(ntfs_volume *vol)
if (vol_is_dirty == TRUE)
return 0;
printf("Setting required flags on partition... ");
ntfs_log_info("Setting required flags on partition... ");
/*
* Set chkdsk flag, i.e. mark the partition dirty so chkdsk will run
* and fix it for us.
@ -250,15 +262,18 @@ static int set_dirty_flag(ntfs_volume *vol)
if (vol->major_ver >= 2)
flags |= VOLUME_MOUNTED_ON_NT4;
if (OLD_ntfs_volume_set_flags(vol, flags)) {
puts(FAILED);
fprintf(stderr, "Error setting volume flags.\n");
ntfs_log_info(FAILED);
ntfs_log_error("Error setting volume flags.\n");
return -1;
}
puts(OK);
ntfs_log_info(OK);
vol_is_dirty = TRUE;
return 0;
}
/**
* set_dirty_flag_mount
*/
static int set_dirty_flag_mount(ntfs_volume *vol)
{
u16 flags;
@ -266,7 +281,7 @@ static int set_dirty_flag_mount(ntfs_volume *vol)
if (vol_is_dirty == TRUE)
return 0;
printf("Setting required flags on partition... ");
ntfs_log_info("Setting required flags on partition... ");
/*
* Set chkdsk flag, i.e. mark the partition dirty so chkdsk will run
* and fix it for us.
@ -276,31 +291,37 @@ static int set_dirty_flag_mount(ntfs_volume *vol)
if (vol->major_ver >= 2)
flags |= VOLUME_MOUNTED_ON_NT4;
if (ntfs_volume_write_flags(vol, flags)) {
puts(FAILED);
fprintf(stderr, "Error setting volume flags.\n");
ntfs_log_info(FAILED);
ntfs_log_error("Error setting volume flags.\n");
return -1;
}
puts(OK);
ntfs_log_info(OK);
vol_is_dirty = TRUE;
return 0;
}
/**
* empty_journal
*/
static int empty_journal(ntfs_volume *vol)
{
if (journal_is_empty == TRUE)
return 0;
printf("Going to empty the journal ($LogFile)... ");
ntfs_log_info("Going to empty the journal ($LogFile)... ");
if (ntfs_logfile_reset(vol)) {
puts(FAILED);
perror("Failed to reset $LogFile");
ntfs_log_info(FAILED);
ntfs_log_perror("Failed to reset $LogFile");
return -1;
}
puts(OK);
ntfs_log_info(OK);
journal_is_empty = TRUE;
return 0;
}
/**
* fix_mftmirr
*/
static int fix_mftmirr(ntfs_volume *vol)
{
s64 l, br;
@ -308,44 +329,44 @@ static int fix_mftmirr(ntfs_volume *vol)
int i, ret = -1; /* failure */
BOOL done;
puts("\nProcessing $MFT and $MFTMirr... ");
ntfs_log_info("\nProcessing $MFT and $MFTMirr...\n");
/* Load data from $MFT and $MFTMirr and compare the contents. */
m = (u8*)malloc(vol->mftmirr_size << vol->mft_record_size_bits);
if (!m) {
perror("Failed to allocate memory");
ntfs_log_perror("Failed to allocate memory");
return -1;
}
m2 = (u8*)malloc(vol->mftmirr_size << vol->mft_record_size_bits);
if (!m2) {
perror("Failed to allocate memory");
ntfs_log_perror("Failed to allocate memory");
free(m);
return -1;
}
printf("Reading $MFT... ");
ntfs_log_info("Reading $MFT... ");
l = ntfs_attr_mst_pread(vol->mft_na, 0, vol->mftmirr_size,
vol->mft_record_size, m);
if (l != vol->mftmirr_size) {
puts(FAILED);
ntfs_log_info(FAILED);
if (l != -1)
errno = EIO;
perror("Failed to read $MFT");
ntfs_log_perror("Failed to read $MFT");
goto error_exit;
}
puts(OK);
ntfs_log_info(OK);
printf("Reading $MFTMirr... ");
ntfs_log_info("Reading $MFTMirr... ");
l = ntfs_attr_mst_pread(vol->mftmirr_na, 0, vol->mftmirr_size,
vol->mft_record_size, m2);
if (l != vol->mftmirr_size) {
puts(FAILED);
ntfs_log_info(FAILED);
if (l != -1)
errno = EIO;
perror("Failed to read $MFTMirr");
ntfs_log_perror("Failed to read $MFTMirr");
goto error_exit;
}
puts(OK);
ntfs_log_info(OK);
/*
* FIXME: Need to actually check the $MFTMirr for being real. Otherwise
@ -359,7 +380,7 @@ static int fix_mftmirr(ntfs_volume *vol)
* MD disk and if yes then bomb out right at the start of the program?
*/
printf("Comparing $MFTMirr to $MFT... ");
ntfs_log_info("Comparing $MFTMirr to $MFT... ");
done = FALSE;
for (i = 0; i < vol->mftmirr_size; ++i) {
const char *ESTR[12] = { "$MFT", "$MFTMirr", "$LogFile",
@ -375,22 +396,22 @@ static int fix_mftmirr(ntfs_volume *vol)
s = "mft record";
if (ntfs_is_baad_recordp(m + i * vol->mft_record_size)) {
puts("FAILED");
fprintf(stderr, "$MFT error: Incomplete multi sector "
ntfs_log_info("FAILED");
ntfs_log_error("$MFT error: Incomplete multi sector "
"transfer detected in %s.\nCannot "
"handle this yet. )-:\n", s);
goto error_exit;
}
if (!ntfs_is_mft_recordp(m + i * vol->mft_record_size)) {
puts("FAILED");
fprintf(stderr, "$MFT error: Invalid mft record for "
ntfs_log_info("FAILED");
ntfs_log_error("$MFT error: Invalid mft record for "
"%s.\nCannot handle this yet. )-:\n",
s);
goto error_exit;
}
if (ntfs_is_baad_recordp(m2 + i * vol->mft_record_size)) {
puts("FAILED");
fprintf(stderr, "$MFTMirr error: Incomplete multi "
ntfs_log_info("FAILED");
ntfs_log_error("$MFTMirr error: Incomplete multi "
"sector transfer detected in %s.\n", s);
goto error_exit;
}
@ -400,20 +421,20 @@ static int fix_mftmirr(ntfs_volume *vol)
(u8*)m + i * vol->mft_record_size)))) {
if (!done) {
done = TRUE;
puts(FAILED);
printf("Correcting differences in $MFTMirr...");
ntfs_log_info(FAILED);
ntfs_log_info("Correcting differences in $MFTMirr...");
}
br = ntfs_mft_record_write(vol, i, (MFT_RECORD*)(m +
i * vol->mft_record_size));
if (br) {
puts(FAILED);
perror("Error correcting $MFTMirr");
ntfs_log_info(FAILED);
ntfs_log_perror("Error correcting $MFTMirr");
goto error_exit;
}
}
}
puts(OK);
printf("Processing of $MFT and $MFTMirr completed successfully.\n");
ntfs_log_info(OK);
ntfs_log_info("Processing of $MFT and $MFTMirr completed successfully.\n");
ret = 0;
error_exit:
free(m);
@ -421,26 +442,29 @@ error_exit:
return ret;
}
/**
* fix_mount
*/
static int fix_mount(void)
{
int ret = -1; /* failure */
ntfs_volume *vol;
struct ntfs_device *dev;
printf("Attempting to correct errors... ");
ntfs_log_info("Attempting to correct errors... ");
dev = ntfs_device_alloc(opt.volume, 0, &ntfs_device_default_io_ops, NULL);
if (!dev) {
puts(FAILED);
perror("Failed to allocate device");
ntfs_log_info(FAILED);
ntfs_log_perror("Failed to allocate device");
return -1;
}
vol = ntfs_volume_startup(dev, 0);
if (!vol) {
puts(FAILED);
perror("Failed to startup volume");
fprintf(stderr, "Volume is corrupt. You should run chkdsk.\n");
ntfs_log_info(FAILED);
ntfs_log_perror("Failed to startup volume");
ntfs_log_error("Volume is corrupt. You should run chkdsk.\n");
ntfs_device_free(dev);
return -1;
}
@ -473,41 +497,43 @@ int main(int argc, char **argv)
int ret = 1; /* failure */
BOOL force = FALSE;
ntfs_log_set_handler(ntfs_log_handler_outerr);
parse_options(argc, argv);
if (!ntfs_check_if_mounted(opt.volume, &mnt_flags)) {
if ((mnt_flags & NTFS_MF_MOUNTED) &&
!(mnt_flags & NTFS_MF_READONLY) && !force) {
fprintf(stderr, "Refusing to operate on read-write "
ntfs_log_error("Refusing to operate on read-write "
"mounted device %s.\n", opt.volume);
exit(1);
}
} else
fprintf(stderr, "Failed to determine whether %s is mounted: "
"%s\n", opt.volume, strerror(errno));
ntfs_log_perror("Failed to determine whether %s is mounted",
opt.volume);
/* Attempt a full mount first. */
printf("Mounting volume... ");
ntfs_log_info("Mounting volume... ");
vol = ntfs_mount(opt.volume, 0);
if (vol) {
puts(OK);
printf("Processing of $MFT and $MFTMirr completed "
ntfs_log_info(OK);
ntfs_log_info("Processing of $MFT and $MFTMirr completed "
"successfully.\n");
} else {
puts(FAILED);
ntfs_log_info(FAILED);
if (fix_mount() < 0)
exit(1);
vol = ntfs_mount(opt.volume, 0);
if (!vol) {
perror("Remount failed");
ntfs_log_perror("Remount failed");
exit(1);
}
}
/* Check NTFS version is ok for us (in $Volume) */
printf("NTFS volume version is %i.%i.\n", vol->major_ver,
ntfs_log_info("NTFS volume version is %i.%i.\n", vol->major_ver,
vol->minor_ver);
if (ntfs_version_is_supported(vol)) {
fprintf(stderr, "Error: Unknown NTFS version.\n");
ntfs_log_error("Error: Unknown NTFS version.\n");
goto error_exit;
}
@ -527,7 +553,7 @@ int main(int argc, char **argv)
/* FIXME: Should we be marking the quota out of date, too? */
/* That's all for now! */
printf("NTFS partition %s was processed successfully.\n",
ntfs_log_info("NTFS partition %s was processed successfully.\n",
vol->dev->d_name);
/* Set return code to 0. */
ret = 0;

View File

@ -64,6 +64,7 @@
#include "mft.h"
#include "utils.h"
#include "version.h"
#include "logging.h"
static const char *EXEC_NAME = "ntfsmftalloc";
@ -88,42 +89,6 @@ static struct {
/* -V, print version and exit. */
} opts;
/**
* mkDprintf - debugging output (-vv); overridden by quiet (-q)
*/
__attribute__((format(printf, 1, 2)))
static void mkDprintf(const char *fmt, ...)
{
va_list ap;
if (!opts.quiet && opts.verbose > 1) {
printf("DEBUG: ");
va_start(ap, fmt);
vprintf(fmt, ap);
va_end(ap);
}
}
/**
* Eprintf - error output; ignores quiet (-q)
*/
int Eprintf(const char *fmt, ...)
{
va_list ap;
fprintf(stderr, "ERROR: ");
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
va_end(ap);
return 0;
}
/* Generate code for Vprintf() function: Verbose output (-v). */
GEN_PRINTF(Vprintf, stdout, &opts.verbose, TRUE)
/* Generate code for Qprintf() function: Quietable output (if not -q). */
GEN_PRINTF(Qprintf, stdout, &opts.quiet, FALSE)
/**
* err_exit - error output and terminate; ignores quiet (-q)
*/
@ -146,7 +111,7 @@ static void err_exit(const char *fmt, ...)
*/
static void copyright(void)
{
fprintf(stderr, "Copyright (c) 2004-2005 Anton Altaparmakov\n"
ntfs_log_info("Copyright (c) 2004-2005 Anton Altaparmakov\n"
"Allocate and initialize a base or an extent mft "
"record. If a base mft record\nis not specified, a "
"base mft record is allocated and initialized. "
@ -160,7 +125,7 @@ static void copyright(void)
*/
static void license(void)
{
fprintf(stderr, "%s", ntfs_gpl);
ntfs_log_info("%s", ntfs_gpl);
}
/**
@ -170,7 +135,7 @@ __attribute__((noreturn))
static void usage(void)
{
copyright();
fprintf(stderr, "Usage: %s [options] device [base-mft-record]\n"
ntfs_log_info("Usage: %s [options] device [base-mft-record]\n"
" -n Do not write to disk\n"
" -f Force execution despite errors\n"
" -q Quiet execution\n"
@ -179,7 +144,7 @@ static void usage(void)
" -V Display version information\n"
" -l Display licensing information\n"
" -h Display this help\n", EXEC_NAME);
fprintf(stderr, "%s%s", ntfs_bugs, ntfs_home);
ntfs_log_info("%s%s", ntfs_bugs, ntfs_home);
exit(1);
}
@ -194,9 +159,9 @@ static void parse_options(int argc, char *argv[])
if (argc && *argv)
EXEC_NAME = *argv;
fprintf(stderr, "%s v%s (libntfs %s)\n", EXEC_NAME, VERSION,
ntfs_log_info("%s v%s (libntfs %s)\n", EXEC_NAME, VERSION,
ntfs_libntfs_version());
while ((c = getopt(argc, argv, "fh?nqvVl")) != EOF)
while ((c = getopt(argc, argv, "fh?nqvVl")) != EOF) {
switch (c) {
case 'f':
opts.force = 1;
@ -206,9 +171,11 @@ static void parse_options(int argc, char *argv[])
break;
case 'q':
opts.quiet = 1;
ntfs_log_clear_levels(NTFS_LOG_LEVEL_QUIET);
break;
case 'v':
opts.verbose++;
ntfs_log_set_levels(NTFS_LOG_LEVEL_VERBOSE);
break;
case 'V':
/* Version number already printed, so just exit. */
@ -222,11 +189,17 @@ static void parse_options(int argc, char *argv[])
default:
usage();
}
}
if (opts.verbose > 1)
ntfs_log_set_levels(NTFS_LOG_LEVEL_DEBUG | NTFS_LOG_LEVEL_TRACE |
NTFS_LOG_LEVEL_VERBOSE | NTFS_LOG_LEVEL_QUIET);
if (optind == argc)
usage();
/* Get the device. */
dev_name = argv[optind++];
mkDprintf("device name = %s\n", dev_name);
ntfs_log_verbose("device name = %s\n", dev_name);
if (optind != argc) {
/* Get the base mft record number. */
ll = strtoll(argv[optind++], &s, 0);
@ -234,7 +207,7 @@ static void parse_options(int argc, char *argv[])
err_exit("Invalid base mft record number: %s\n",
argv[optind - 1]);
base_mft_no = ll;
mkDprintf("base mft record number = 0x%llx\n", (long long)ll);
ntfs_log_verbose("base mft record number = 0x%llx\n", (long long)ll);
}
if (optind != argc)
usage();
@ -249,46 +222,46 @@ static void dump_mft_record(MFT_RECORD *m)
unsigned int u;
MFT_REF r;
printf("-- Beginning dump of mft record. --\n");
ntfs_log_info("-- Beginning dump of mft record. --\n");
u = le32_to_cpu(m->magic);
printf("Mft record signature (magic) = %c%c%c%c\n", u & 0xff,
ntfs_log_info("Mft record signature (magic) = %c%c%c%c\n", u & 0xff,
u >> 8 & 0xff, u >> 16 & 0xff, u >> 24 & 0xff);
u = le16_to_cpu(m->usa_ofs);
printf("Update sequence array offset = %u (0x%x)\n", u, u);
printf("Update sequence array size = %u\n", le16_to_cpu(m->usa_count));
printf("$LogFile sequence number (lsn) = %llu\n",
ntfs_log_info("Update sequence array offset = %u (0x%x)\n", u, u);
ntfs_log_info("Update sequence array size = %u\n", le16_to_cpu(m->usa_count));
ntfs_log_info("$LogFile sequence number (lsn) = %llu\n",
(unsigned long long)le64_to_cpu(m->lsn));
printf("Sequence number = %u\n", le16_to_cpu(m->sequence_number));
printf("Reference (hard link) count = %u\n",
ntfs_log_info("Sequence number = %u\n", le16_to_cpu(m->sequence_number));
ntfs_log_info("Reference (hard link) count = %u\n",
le16_to_cpu(m->link_count));
u = le16_to_cpu(m->attrs_offset);
printf("First attribute offset = %u (0x%x)\n", u, u);
printf("Flags = %u: ", le16_to_cpu(m->flags));
ntfs_log_info("First attribute offset = %u (0x%x)\n", u, u);
ntfs_log_info("Flags = %u: ", le16_to_cpu(m->flags));
if (m->flags & MFT_RECORD_IN_USE)
printf("MFT_RECORD_IN_USE");
ntfs_log_info("MFT_RECORD_IN_USE");
else
printf("MFT_RECORD_NOT_IN_USE");
ntfs_log_info("MFT_RECORD_NOT_IN_USE");
if (m->flags & MFT_RECORD_IS_DIRECTORY)
printf(" | MFT_RECORD_IS_DIRECTORY");
printf("\n");
ntfs_log_info(" | MFT_RECORD_IS_DIRECTORY");
ntfs_log_info("\n");
u = le32_to_cpu(m->bytes_in_use);
printf("Bytes in use = %u (0x%x)\n", u, u);
ntfs_log_info("Bytes in use = %u (0x%x)\n", u, u);
u = le32_to_cpu(m->bytes_allocated);
printf("Bytes allocated = %u (0x%x)\n", u, u);
ntfs_log_info("Bytes allocated = %u (0x%x)\n", u, u);
r = le64_to_cpu(m->base_mft_record);
printf("Base mft record reference:\n\tMft record number = %llu\n\t"
ntfs_log_info("Base mft record reference:\n\tMft record number = %llu\n\t"
"Sequence number = %u\n",
(unsigned long long)MREF(r), MSEQNO(r));
printf("Next attribute instance = %u\n",
ntfs_log_info("Next attribute instance = %u\n",
le16_to_cpu(m->next_attr_instance));
a = (ATTR_RECORD*)((char*)m + le16_to_cpu(m->attrs_offset));
printf("-- Beginning dump of attributes within mft record. --\n");
ntfs_log_info("-- Beginning dump of attributes within mft record. --\n");
while ((char*)a < (char*)m + le32_to_cpu(m->bytes_in_use)) {
if (a->type == AT_END)
break;
a = (ATTR_RECORD*)((char*)a + le32_to_cpu(a->length));
};
printf("-- End of attributes. --\n");
ntfs_log_info("-- End of attributes. --\n");
}
/**
@ -303,13 +276,12 @@ static void ntfsmftalloc_exit(void)
ni = base_ni;
/* Close the inode. */
if (ni && ntfs_inode_close(ni)) {
fprintf(stderr, "Warning: Failed to close inode 0x%llx: %s\n",
(long long)ni->mft_no, strerror(errno));
ntfs_log_perror("Warning: Failed to close inode 0x%llx",
(long long)ni->mft_no);
}
/* Unmount the volume. */
if (ntfs_umount(vol, 0) == -1)
fprintf(stderr, "Warning: Could not umount %s: %s\n", dev_name,
strerror(errno));
ntfs_log_perror("Warning: Could not umount %s", dev_name);
}
/**
@ -320,6 +292,8 @@ int main(int argc, char **argv)
unsigned long mnt_flags, ul;
int err;
ntfs_log_set_handler(ntfs_log_handler_outerr);
/* Initialize opts to zero / required values. */
memset(&opts, 0, sizeof(opts));
/* Parse command line options. */
@ -327,18 +301,18 @@ int main(int argc, char **argv)
utils_set_locale();
/* Make sure the file system is not mounted. */
if (ntfs_check_if_mounted(dev_name, &mnt_flags))
Eprintf("Failed to determine whether %s is mounted: %s\n",
ntfs_log_error("Failed to determine whether %s is mounted: %s\n",
dev_name, strerror(errno));
else if (mnt_flags & NTFS_MF_MOUNTED) {
Eprintf("%s is mounted.\n", dev_name);
ntfs_log_error("%s is mounted.\n", dev_name);
if (!opts.force)
err_exit("Refusing to run!\n");
fprintf(stderr, "ntfsmftalloc forced anyway. Hope /etc/mtab "
ntfs_log_error("ntfsmftalloc forced anyway. Hope /etc/mtab "
"is incorrect.\n");
}
/* Mount the device. */
if (opts.no_action) {
Qprintf("Running in READ-ONLY mode!\n");
ntfs_log_quiet("Running in READ-ONLY mode!\n");
ul = MS_RDONLY;
} else
ul = 0;
@ -348,7 +322,7 @@ int main(int argc, char **argv)
/* Register our exit function which will unlock and close the device. */
err = atexit(&ntfsmftalloc_exit);
if (err == -1) {
Eprintf("Could not set up exit() function because atexit() "
ntfs_log_error("Could not set up exit() function because atexit() "
"failed: %s Aborting...\n", strerror(errno));
ntfsmftalloc_exit();
exit(1);
@ -365,14 +339,14 @@ int main(int argc, char **argv)
if (!ni)
err_exit("Failed to allocate mft record: %s\n",
strerror(errno));
printf("Allocated %s mft record 0x%llx", base_ni ? "extent" : "base",
ntfs_log_info("Allocated %s mft record 0x%llx", base_ni ? "extent" : "base",
(long long)ni->mft_no);
if (base_ni)
printf(" with base mft record 0x%llx",
ntfs_log_info(" with base mft record 0x%llx",
(long long)base_mft_no);
printf(".\n");
ntfs_log_info(".\n");
if (!opts.quiet && opts.verbose > 1) {
mkDprintf("Dumping allocated mft record 0x%llx:\n",
ntfs_log_verbose("Dumping allocated mft record 0x%llx:\n",
(long long)ni->mft_no);
dump_mft_record(ni->mrec);
}
@ -388,9 +362,8 @@ int main(int argc, char **argv)
/* Disable our ntfsmftalloc_exit() handler. */
success = TRUE;
if (err == -1)
fprintf(stderr, "Warning: Failed to umount %s: %s\n", dev_name,
strerror(errno));
ntfs_log_perror("Warning: Failed to umount %s", dev_name);
else
Qprintf("ntfsmftalloc completed successfully.\n");
ntfs_log_quiet("ntfsmftalloc completed successfully.\n");
return 0;
}

View File

@ -66,10 +66,10 @@ static const char *space_line = "
*/
static void version(void)
{
printf("\n%s v%s (libntfs %s) - Delete files from an NTFS volume.\n\n",
ntfs_log_info("\n%s v%s (libntfs %s) - Delete files from an NTFS volume.\n\n",
EXEC_NAME, VERSION, ntfs_libntfs_version());
printf("Copyright (c) 2004 Richard Russon\n");
printf("\n%s\n%s%s\n", ntfs_gpl, ntfs_bugs, ntfs_home);
ntfs_log_info("Copyright (c) 2004 Richard Russon\n");
ntfs_log_info("\n%s\n%s%s\n", ntfs_gpl, ntfs_bugs, ntfs_home);
}
/**
@ -81,7 +81,7 @@ static void version(void)
*/
static void usage(void)
{
printf("\nUsage: %s [options] device file\n"
ntfs_log_info("\nUsage: %s [options] device file\n"
"\n"
" -r --recursive Delete files in subdirectories\n"
" -i --interactive Ask before deleting files\n"
@ -96,7 +96,7 @@ static void usage(void)
" -V --version Version information\n"
" -v --verbose More output\n\n",
EXEC_NAME);
printf("%s%s\n", ntfs_bugs, ntfs_home);
ntfs_log_info("%s%s\n", ntfs_bugs, ntfs_home);
}
/**
@ -130,6 +130,7 @@ static int parse_options(int argc, char **argv)
int err = 0;
int ver = 0;
int help = 0;
int levels = 0;
opterr = 0; /* We'll handle the errors, thank you. */
@ -154,6 +155,11 @@ static int parse_options(int argc, char **argv)
break;
case 'h':
case '?':
if (strncmp (argv[optind-1], "--log-", 6) == 0) {
if (!ntfs_log_parse_option (argv[optind-1]))
err++;
break;
}
help++;
break;
case 'i':
@ -164,6 +170,7 @@ static int parse_options(int argc, char **argv)
break;
case 'q':
opts.quiet++;
ntfs_log_clear_levels(NTFS_LOG_LEVEL_QUIET);
break;
case 'R':
case 'r':
@ -174,6 +181,7 @@ static int parse_options(int argc, char **argv)
break;
case 'v':
opts.verbose++;
ntfs_log_set_levels(NTFS_LOG_LEVEL_VERBOSE);
break;
default:
ntfs_log_error("Unknown option '%s'.\n", argv[optind-1]);
@ -182,6 +190,13 @@ static int parse_options(int argc, char **argv)
}
}
/* Make sure we're in sync with the log levels */
levels = ntfs_log_get_levels();
if (levels & NTFS_LOG_LEVEL_VERBOSE)
opts.verbose++;
if (!(levels & NTFS_LOG_LEVEL_QUIET))
opts.quiet++;
if (help || ver) {
opts.quiet = 0;
} else {
@ -217,9 +232,9 @@ static void ntfs_dir_print(struct ntfs_dir *dir, int indent)
if (!dir)
return;
printf("%.*s%p ", indent, space_line, dir);
ntfs_log_info("%.*s%p ", indent, space_line, dir);
ntfs_name_print(dir->name, dir->name_len);
printf("\n");
ntfs_log_info("\n");
for (i = 0; i < dir->child_count; i++) {
ntfs_dir_print(dir->children[i], indent + 4);
@ -237,7 +252,7 @@ static void ntfs_dt_print(struct ntfs_dt *dt, int indent)
if (!dt)
return;
printf("%.*s%p (%d)\n", indent, space_line, dt, dt->child_count);
ntfs_log_info("%.*s%p (%d)\n", indent, space_line, dt, dt->child_count);
for (i = 0; i < dt->child_count; i++) {
ntfs_dt_print(dt->sub_nodes[i], indent + 4);
@ -359,32 +374,32 @@ static BOOL utils_pathname_to_inode2(ntfs_volume *vol, struct ntfs_dir *parent,
goto close;
}
//printf("looking for %s in dir %lld\n", p, MREF(dir->mft_num));
//printf("dir: index = %p, children = %p, inode = %p, iroot = %p, ialloc = %p, count = %d\n", dir->index, dir->children, dir->inode, dir->iroot, dir->ialloc, dir->child_count);
//ntfs_log_info("looking for %s in dir %lld\n", p, MREF(dir->mft_num));
//ntfs_log_info("dir: index = %p, children = %p, inode = %p, iroot = %p, ialloc = %p, count = %d\n", dir->index, dir->children, dir->inode, dir->iroot, dir->ialloc, dir->child_count);
//if (dir->parent)
if (q) {
ntfs_log_trace("q\n");
child = ntfs_dir_find2(dir, unicode, len);
if (!child) {
printf("can't find %s in %s\n", p, pathname);
ntfs_log_info("can't find %s in %s\n", p, pathname);
goto close;
}
} else {
ntfs_log_trace("!q dir->index = %p, %d\n", dir->index, dir->index->data_len);
//printf("file: %s\n", p);
//ntfs_log_info("file: %s\n", p);
dt = ntfs_dt_find2(dir->index, unicode, len, &dt_num);
if (!dt) {
printf("can't find %s in %s (2)\n", p, pathname);
ntfs_log_info("can't find %s in %s (2)\n", p, pathname);
goto close;
}
ntfs_log_debug("dt = %p, data_len = %d, parent = %p\n", dt, dt->data_len, dt->parent);
//printf("dt's flags = 0x%08x\n", dt->children[dt_num]->key.file_name.file_attributes);
//ntfs_log_info("dt's flags = 0x%08x\n", dt->children[dt_num]->key.file_name.file_attributes);
if (dt->children[dt_num]->key.file_name.file_attributes == FILE_ATTR_I30_INDEX_PRESENT) {
//printf("DIR\n");
//ntfs_log_info("DIR\n");
child = ntfs_dir_create(dir->vol, dt->children[dt_num]->indexed_file);
//printf("child = %p (%lld)\n", child, MREF(dt->children[dt_num]->indexed_file));
//ntfs_log_info("child = %p (%lld)\n", child, MREF(dt->children[dt_num]->indexed_file));
if (child) {
child->index = ntfs_dt_create(child, NULL, -1);
ntfs_dir_add(dir, child);
@ -395,14 +410,14 @@ static BOOL utils_pathname_to_inode2(ntfs_volume *vol, struct ntfs_dir *parent,
if (dt->inodes[dt_num] == NULL) {
dt->inodes[dt_num] = ntfs_inode_open(dir->vol, dt->children[dt_num]->indexed_file);
if (!dt->inodes[dt_num]) {
printf("Can't open inode %lld\n", MREF(dt->children[dt_num]->indexed_file));
ntfs_log_info("Can't open inode %lld\n", MREF(dt->children[dt_num]->indexed_file));
goto close;
}
dt->inodes[dt_num]->ref_count = 2;
dt->inodes[dt_num]->private_data = dt;
}
//printf("dt = %p,%d\n", dt, dt_num);
//ntfs_log_info("dt = %p,%d\n", dt, dt_num);
break;
}
@ -419,7 +434,7 @@ static BOOL utils_pathname_to_inode2(ntfs_volume *vol, struct ntfs_dir *parent,
found->inode = dt->inodes[dt_num];
found->mref = found->inode->mft_no;
result = TRUE;
//printf("dir %p, dt %p, num %d, ino %p, %lld\n", dir, dt, dt_num, dt->inodes[dt_num], MREF(found->inode->mft_no));
//ntfs_log_info("dir %p, dt %p, num %d, ino %p, %lld\n", dir, dt, dt_num, dt->inodes[dt_num], MREF(found->inode->mft_no));
close:
free(ascii); // from strdup
free(unicode);
@ -440,7 +455,7 @@ static s64 ntfs_mft_find_free_entry(ntfs_volume *vol)
ntfs_log_trace ("\n");
recs = vol->mft_na->initialized_size >> vol->mft_record_size_bits;
//printf("mft contains %lld records\n", recs);
//ntfs_log_info("mft contains %lld records\n", recs);
for (i = 24; i < recs; i++) {
if (utils_mftrec_in_use(vol, i) == 0)
return i;
@ -475,7 +490,7 @@ static int ntfs_mft_set_inuse6(ntfs_inode *inode, struct ntfs_bmp *bmp, BOOL inu
NInoSetDirty(inode);
printf("Modified: inode %lld MFT_RECORD header\n", inode->mft_no);
ntfs_log_info("Modified: inode %lld MFT_RECORD header\n", inode->mft_no);
return 0;
}
@ -520,7 +535,7 @@ static int ntfs_file_remove(ntfs_volume *vol, struct ntfs_dt *del, int del_num)
del_ie = del->children[del_num];
//utils_dump_mem(del_ie, 0, del_ie->length, DM_DEFAULTS);
//printf("\n");
//ntfs_log_info("\n");
/*
* If the key is not in a leaf node, then replace it with its successor.
@ -530,38 +545,38 @@ static int ntfs_file_remove(ntfs_volume *vol, struct ntfs_dt *del, int del_num)
/*
for (i = 0; i < top->child_count; i++) {
par_ie = top->children[i];
file = &par_ie->key.file_name; printf("\ttop node, key %d: ", i); ntfs_name_print(file->file_name, file->file_name_length); printf("\n");
printf("\tvcn = %lld\n", ntfs_ie_get_vcn(par_ie));
file = &par_ie->key.file_name; ntfs_log_info("\ttop node, key %d: ", i); ntfs_name_print(file->file_name, file->file_name_length); ntfs_log_info("\n");
ntfs_log_info("\tvcn = %lld\n", ntfs_ie_get_vcn(par_ie));
}
*/
if (del->header->flags & INDEX_NODE) {
printf("Replace key with its successor:\n");
ntfs_log_info("Replace key with its successor:\n");
vcn = ntfs_ie_get_vcn(del_ie);
//printf("vcn = %lld\n", vcn);
//ntfs_log_info("vcn = %lld\n", vcn);
suc = ntfs_dt_find4(find_dir->index, uname, name_len, &suc_num);
//printf("succ = %p, index = %d\n", suc, suc_num);
//printf("\n");
//ntfs_log_info("succ = %p, index = %d\n", suc, suc_num);
//ntfs_log_info("\n");
suc_ie = ntfs_ie_copy(suc->children[suc_num]);
//utils_dump_mem(suc_ie, 0, suc_ie->length, DM_BLUE|DM_GREEN|DM_INDENT);
//printf("\n");
//ntfs_log_info("\n");
suc_ie = ntfs_ie_set_vcn(suc_ie, vcn);
//utils_dump_mem(suc_ie, 0, suc_ie->length, DM_BLUE|DM_GREEN|DM_INDENT);
//printf("\n");
//ntfs_log_info("\n");
file = &del_ie->key.file_name; printf("\trep name: "); ntfs_name_print(file->file_name, file->file_name_length); printf("\n");
file = &suc_ie->key.file_name; printf("\tsuc name: "); ntfs_name_print(file->file_name, file->file_name_length); printf("\n");
file = &del_ie->key.file_name; ntfs_log_info("\trep name: "); ntfs_name_print(file->file_name, file->file_name_length); ntfs_log_info("\n");
file = &suc_ie->key.file_name; ntfs_log_info("\tsuc name: "); ntfs_name_print(file->file_name, file->file_name_length); ntfs_log_info("\n");
//utils_dump_mem(del->data, 0, del->data_len, DM_BLUE|DM_GREEN|DM_INDENT);
if (ntfs_dt_isroot(del))
res = ntfs_dt_root_replace(del, del_num, del_ie, suc_ie);
else
res = ntfs_dt_alloc_replace(del, del_num, del_ie, suc_ie);
//printf("\n");
//ntfs_log_info("\n");
//utils_dump_mem(del->data, 0, del->data_len, DM_BLUE|DM_GREEN|DM_INDENT);
ntfs_ie_free(suc_ie);
@ -581,10 +596,10 @@ static int ntfs_file_remove(ntfs_volume *vol, struct ntfs_dt *del, int del_num)
* If this step creates an empty node, we have more to do.
*/
printf("\n");
printf("Delete key:\n");
ntfs_log_info("\n");
ntfs_log_info("Delete key:\n");
file = &del->children[del_num]->key.file_name; printf("\tdel name: "); ntfs_name_print(file->file_name, file->file_name_length); printf("\n");
file = &del->children[del_num]->key.file_name; ntfs_log_info("\tdel name: "); ntfs_name_print(file->file_name, file->file_name_length); ntfs_log_info("\n");
//utils_dump_mem(del->data, 0, del->header->index_length+24, DM_BLUE|DM_GREEN|DM_INDENT);
// XXX if del->child_count == 2, we could skip this step
@ -593,7 +608,7 @@ static int ntfs_file_remove(ntfs_volume *vol, struct ntfs_dt *del, int del_num)
ntfs_dt_root_remove(del, del_num);
else
ntfs_dt_alloc_remove(del, del_num);
//printf("\n");
//ntfs_log_info("\n");
//utils_dump_mem(del->data, 0, del->header->index_length+24, DM_BLUE|DM_GREEN|DM_INDENT);
if (del->child_count > 1) // XXX ntfs_dt_empty (dt), ntfs_dt_full (dt, new)
@ -607,8 +622,8 @@ static int ntfs_file_remove(ntfs_volume *vol, struct ntfs_dt *del, int del_num)
*/
// find the key nearest the root which has no descendants
printf("\n");
printf("Find childless parent:\n");
ntfs_log_info("\n");
ntfs_log_info("Find childless parent:\n");
#if 0
for (par = del->parent, old = par; par; old = par, par = par->parent) {
if (par->child_count > 1)
@ -617,20 +632,20 @@ static int ntfs_file_remove(ntfs_volume *vol, struct ntfs_dt *del, int del_num)
}
#endif
printf("del = %p, parent = %p\n", del, del->parent);
ntfs_log_info("del = %p, parent = %p\n", del, del->parent);
par = del->parent;
par_num = ntfs_dt_find_parent(del);
//utils_dump_mem(par->data, 0, par->data_len, DM_BLUE|DM_GREEN|DM_INDENT);
printf("par = %p, par->parent = %p, num = %d\n", par, par->parent, par_num);
ntfs_log_info("par = %p, par->parent = %p, num = %d\n", par, par->parent, par_num);
par_num = 0; // TEMP
if (par) {
file = &par->children[par_num]->key.file_name;
printf("\tpar name: ");
ntfs_log_info("\tpar name: ");
ntfs_name_print(file->file_name, file->file_name_length);
printf("\n");
ntfs_log_info("\n");
}
if (par == NULL) {
@ -639,35 +654,35 @@ static int ntfs_file_remove(ntfs_volume *vol, struct ntfs_dt *del, int del_num)
}
//ntfs_dt_print(top, 0);
printf("\n");
ntfs_log_info("\n");
//utils_dump_mem(par->data, 0, par->data_len, DM_BLUE|DM_GREEN|DM_INDENT);
//printf("\n");
//ntfs_log_info("\n");
/*
for (i = 0; i < top->child_count; i++) {
par_ie = top->children[i];
file = &par_ie->key.file_name; printf("\ttop node, key %d: ", i); ntfs_name_print(file->file_name, file->file_name_length); printf("\n");
printf("\tvcn = %lld\n", ntfs_ie_get_vcn(par_ie));
file = &par_ie->key.file_name; ntfs_log_info("\ttop node, key %d: ", i); ntfs_name_print(file->file_name, file->file_name_length); ntfs_log_info("\n");
ntfs_log_info("\tvcn = %lld\n", ntfs_ie_get_vcn(par_ie));
}
*/
// find if parent has left siblings
if (par->children[par_num]->flags & INDEX_ENTRY_END) {
printf("Swap the children of the parent and its left sibling\n");
ntfs_log_info("Swap the children of the parent and its left sibling\n");
par_ie = par->children[par_num];
vcn = ntfs_ie_get_vcn(par_ie);
//printf("\toffset = %d\n", (u8*)par_ie - par->data); printf("\tflags = %d\n", par_ie->flags); printf("\tvcn = %lld\n", vcn); printf("\tlength = %d\n", par_ie->length);
//ntfs_log_info("\toffset = %d\n", (u8*)par_ie - par->data); ntfs_log_info("\tflags = %d\n", par_ie->flags); ntfs_log_info("\tvcn = %lld\n", vcn); ntfs_log_info("\tlength = %d\n", par_ie->length);
//utils_dump_mem(par_ie, 0, par_ie->length, DM_DEFAULTS);
//printf("\n");
//ntfs_log_info("\n");
//printf("\toffset = %d\n", (u8*)par_ie - par->data); printf("\tflags = %d\n", par_ie->flags); printf("\tvcn = %lld\n", vcn); printf("\tlength = %d\n", par_ie->length);
//ntfs_log_info("\toffset = %d\n", (u8*)par_ie - par->data); ntfs_log_info("\tflags = %d\n", par_ie->flags); ntfs_log_info("\tvcn = %lld\n", vcn); ntfs_log_info("\tlength = %d\n", par_ie->length);
//utils_dump_mem(par_ie, 0, par_ie->length, DM_DEFAULTS);
//printf("\n");
//ntfs_log_info("\n");
file = &par->children[par_num] ->key.file_name; printf("\tpar name: "); ntfs_name_print(file->file_name, file->file_name_length); printf("\n");
file = &par->children[par_num-1]->key.file_name; printf("\tsib name: "); ntfs_name_print(file->file_name, file->file_name_length); printf("\n");
file = &par->children[par_num] ->key.file_name; ntfs_log_info("\tpar name: "); ntfs_name_print(file->file_name, file->file_name_length); ntfs_log_info("\n");
file = &par->children[par_num-1]->key.file_name; ntfs_log_info("\tsib name: "); ntfs_name_print(file->file_name, file->file_name_length); ntfs_log_info("\n");
old = par->sub_nodes[par_num];
par->sub_nodes[par_num] = par->sub_nodes[par_num-1];
@ -682,28 +697,28 @@ static int ntfs_file_remove(ntfs_volume *vol, struct ntfs_dt *del, int del_num)
par_num--;
if (ntfs_dt_isroot(par))
printf("Modified: inode %lld, $INDEX_ROOT\n", par->dir->inode->mft_no);
ntfs_log_info("Modified: inode %lld, $INDEX_ROOT\n", par->dir->inode->mft_no);
else
printf("Modified: inode %lld, $INDEX_ALLOCATION vcn %lld-%lld\n", par->dir->inode->mft_no, par->vcn, par->vcn + (par->dir->index_size>>9) - 1);
ntfs_log_info("Modified: inode %lld, $INDEX_ALLOCATION vcn %lld-%lld\n", par->dir->inode->mft_no, par->vcn, par->vcn + (par->dir->index_size>>9) - 1);
}
//ntfs_dt_print(top, 0);
//printf("\n");
//ntfs_log_info("\n");
//utils_dump_mem(par->data, 0, par->data_len, DM_DEFAULTS);
// unhook and hold onto the ded dt's
printf("\n");
printf("Remove parent\n");
ntfs_log_info("\n");
ntfs_log_info("Remove parent\n");
file = &par->children[par_num]->key.file_name; printf("\tpar name: "); ntfs_name_print(file->file_name, file->file_name_length); printf("\n");
file = &par->children[par_num]->key.file_name; ntfs_log_info("\tpar name: "); ntfs_name_print(file->file_name, file->file_name_length); ntfs_log_info("\n");
add_ie = ntfs_ie_copy(par->children[par_num]);
add_ie = ntfs_ie_remove_vcn(add_ie);
if (!add_ie)
goto done;
//printf("\n");
//ntfs_log_info("\n");
//utils_dump_mem(add_ie, 0, add_ie->length, DM_BLUE|DM_GREEN|DM_INDENT);
ded = par->sub_nodes[par_num];
@ -713,44 +728,44 @@ static int ntfs_file_remove(ntfs_volume *vol, struct ntfs_dt *del, int del_num)
#if 0
for (i = 0; i < par->child_count; i++) {
par_ie = par->children[i];
file = &par_ie->key.file_name; printf("\tdel node, key %d: ", i); ntfs_name_print(file->file_name, file->file_name_length); printf("\n");
printf("\tvcn = %lld\n", ntfs_ie_get_vcn(par_ie));
file = &par_ie->key.file_name; ntfs_log_info("\tdel node, key %d: ", i); ntfs_name_print(file->file_name, file->file_name_length); ntfs_log_info("\n");
ntfs_log_info("\tvcn = %lld\n", ntfs_ie_get_vcn(par_ie));
}
#endif
#if 1
//printf("PAR: %p,%d\n", par, par_num);
//ntfs_log_info("PAR: %p,%d\n", par, par_num);
if (ntfs_dt_isroot(par))
ntfs_dt_root_remove(par, par_num);
else
ntfs_dt_alloc_remove(par, par_num);
#endif
//printf("count = %d\n", par->child_count);
//ntfs_log_info("count = %d\n", par->child_count);
//utils_dump_mem(par->data, 0, par->data_len, DM_DEFAULTS);
//printf("0x%x\n", (u8*)par->children[0] - par->data);
//ntfs_log_info("0x%x\n", (u8*)par->children[0] - par->data);
#if 0
for (i = 0; i < par->child_count; i++) {
par_ie = par->children[i];
file = &par_ie->key.file_name; printf("\tadd node, key %d: ", i); ntfs_name_print(file->file_name, file->file_name_length); printf("\n");
printf("\tvcn = %lld\n", ntfs_ie_get_vcn(par_ie));
file = &par_ie->key.file_name; ntfs_log_info("\tadd node, key %d: ", i); ntfs_name_print(file->file_name, file->file_name_length); ntfs_log_info("\n");
ntfs_log_info("\tvcn = %lld\n", ntfs_ie_get_vcn(par_ie));
}
#endif
//ntfs_dt_print(top, 0);
printf("\n");
printf("Add childless parent\n");
ntfs_log_info("\n");
ntfs_log_info("Add childless parent\n");
file = &add_ie->key.file_name; printf("\tadd name: "); ntfs_name_print(file->file_name, file->file_name_length); printf("\n");
file = &add_ie->key.file_name; ntfs_log_info("\tadd name: "); ntfs_name_print(file->file_name, file->file_name_length); ntfs_log_info("\n");
suc = NULL;
suc_num = -1;
suc = ntfs_dt_find4(top, file->file_name, file->file_name_length, &suc_num);
//printf("SUC: %p, %d\n", suc, suc_num);
//ntfs_log_info("SUC: %p, %d\n", suc, suc_num);
if (!suc)
goto done;
file = &suc->children[suc_num]->key.file_name; printf("\tsuc name: "); ntfs_name_print(file->file_name, file->file_name_length); printf("\n");
file = &suc->children[suc_num]->key.file_name; ntfs_log_info("\tsuc name: "); ntfs_name_print(file->file_name, file->file_name_length); ntfs_log_info("\n");
// insert key into successor
// if any new nodes are needed, reuse the preserved nodes
@ -766,14 +781,14 @@ static int ntfs_file_remove(ntfs_volume *vol, struct ntfs_dt *del, int del_num)
// XXX reduce size of alloc
// XXX if ded, don't write it back, just update bitmap
printf("empty\n");
ntfs_log_info("empty\n");
goto done;
freedts:
printf("\twhole dir is empty\n");
ntfs_log_info("\twhole dir is empty\n");
commit:
//printf("commit\n");
//ntfs_log_info("commit\n");
done:
return 0;
@ -813,8 +828,8 @@ static int ntfs_file_remove2(ntfs_volume *vol, struct ntfs_dt *dt, int dt_num)
if (0) ntfs_volume_rollback(vol);
if (0) printf("last mft = %lld\n", ntfs_bmp_find_last_set(bmp_mft));
if (0) printf("last vol = %lld\n", ntfs_bmp_find_last_set(bmp_vol));
if (0) ntfs_log_info("last mft = %lld\n", ntfs_bmp_find_last_set(bmp_mft));
if (0) ntfs_log_info("last vol = %lld\n", ntfs_bmp_find_last_set(bmp_vol));
return 0;
}
@ -855,9 +870,9 @@ static int ntfs_file_add2(ntfs_volume *vol, char *filename)
filename = ptr + 1;
}
printf("looking for %s\n", dirname);
ntfs_log_info("looking for %s\n", dirname);
if (utils_pathname_to_inode2(vol, NULL, dirname, &find) == FALSE) {
printf("!inode\n");
ntfs_log_info("!inode\n");
return 0;
}
@ -868,10 +883,10 @@ static int ntfs_file_add2(ntfs_volume *vol, char *filename)
if (uname_len < 0)
goto close;
printf("new inode %lld\n", new_num);
ntfs_log_info("new inode %lld\n", new_num);
ino = ntfs_inode_open3(vol, new_num);
if (!ino) {
printf("!ino\n");
ntfs_log_info("!ino\n");
goto close;
}
@ -936,7 +951,7 @@ static int ntfs_file_add2(ntfs_volume *vol, char *filename)
ie = ntfs_ie_create();
ie = ntfs_ie_set_name(ie, uname, uname_len, FILE_NAME_POSIX);
if (!ie) {
printf("!ie\n");
ntfs_log_info("!ie\n");
goto close;
}
@ -1005,10 +1020,10 @@ int main(int argc, char *argv[])
utils_set_locale();
#if 0
printf("sizeof(ntfs_bmp) = %d\n", sizeof(struct ntfs_bmp));
printf("sizeof(ntfs_dt) = %d\n", sizeof(struct ntfs_dt));
printf("sizeof(ntfs_dir) = %d\n", sizeof(struct ntfs_dir));
printf("\n");
ntfs_log_info("sizeof(ntfs_bmp) = %d\n", sizeof(struct ntfs_bmp));
ntfs_log_info("sizeof(ntfs_dt) = %d\n", sizeof(struct ntfs_dt));
ntfs_log_info("sizeof(ntfs_dir) = %d\n", sizeof(struct ntfs_dir));
ntfs_log_info("\n");
#endif
if (opts.noaction)
@ -1018,20 +1033,20 @@ int main(int argc, char *argv[])
//ntfs_log_set_levels (NTFS_LOG_LEVEL_DEBUG);
vol = ntfs_volume_mount2(opts.device, flags, opts.force);
if (!vol) {
printf("!vol\n");
ntfs_log_info("!vol\n");
goto done;
}
#if 0
if (utils_pathname_to_inode2(vol, NULL, opts.file, &find) == FALSE) {
printf("!inode\n");
ntfs_log_info("!inode\n");
goto done;
}
inode = find.inode;
#endif
//printf("inode = %lld\n", inode->mft_no);
//ntfs_log_info("inode = %lld\n", inode->mft_no);
if (0) result = ntfs_file_remove2(vol, find.dt, find.dt_index);
if (1) result = ntfs_file_add2(vol, opts.file);

View File

@ -66,6 +66,7 @@
#include "utils.h"
#include "attrdef.h"
#include "version.h"
#include "logging.h"
const char *EXEC_NAME = "ntfstruncate";
@ -96,42 +97,6 @@ struct {
/* -V, print version and exit. */
} opts;
/**
* mkDprintf - debugging output (-vv); overridden by quiet (-q)
*/
__attribute__((format(printf, 1, 2)))
static void mkDprintf(const char *fmt, ...)
{
va_list ap;
if (!opts.quiet && opts.verbose > 1) {
printf("DEBUG: ");
va_start(ap, fmt);
vprintf(fmt, ap);
va_end(ap);
}
}
/**
* Eprintf - error output; ignores quiet (-q)
*/
int Eprintf(const char *fmt, ...)
{
va_list ap;
fprintf(stderr, "ERROR: ");
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
va_end(ap);
return 0;
}
/* Generate code for Vprintf() function: Verbose output (-v). */
GEN_PRINTF(Vprintf, stdout, &opts.verbose, TRUE)
/* Generate code for Qprintf() function: Quietable output (if not -q). */
GEN_PRINTF(Qprintf, stdout, &opts.quiet, FALSE)
/**
* err_exit - error output and terminate; ignores quiet (-q)
*/
@ -216,9 +181,11 @@ static void parse_options(int argc, char *argv[])
break;
case 'q':
opts.quiet = 1;
ntfs_log_clear_levels(NTFS_LOG_LEVEL_QUIET);
break;
case 'v':
opts.verbose++;
ntfs_log_set_levels(NTFS_LOG_LEVEL_VERBOSE);
break;
case 'V':
/* Version number already printed, so just exit. */
@ -235,9 +202,13 @@ static void parse_options(int argc, char *argv[])
if (optind == argc)
usage();
if (opts.verbose > 1)
ntfs_log_set_levels(NTFS_LOG_LEVEL_DEBUG | NTFS_LOG_LEVEL_TRACE |
NTFS_LOG_LEVEL_VERBOSE | NTFS_LOG_LEVEL_QUIET);
/* Get the device. */
dev_name = argv[optind++];
mkDprintf("device name = %s\n", dev_name);
ntfs_log_verbose("device name = %s\n", dev_name);
if (optind == argc)
usage();
@ -247,7 +218,7 @@ static void parse_options(int argc, char *argv[])
if (*s || !ll || (ll >= LLONG_MAX && errno == ERANGE))
err_exit("Invalid inode number: %s\n", argv[optind - 1]);
inode = ll;
mkDprintf("inode = %lli\n", (long long)inode);
ntfs_log_verbose("inode = %lli\n", (long long)inode);
if (optind == argc)
usage();
@ -287,11 +258,11 @@ static void parse_options(int argc, char *argv[])
attr_name_len = 0;
}
}
mkDprintf("attribute type = 0x%x\n", (unsigned int)attr_type);
ntfs_log_verbose("attribute type = 0x%x\n", (unsigned int)attr_type);
if (attr_name == AT_UNNAMED)
mkDprintf("attribute name = \"\" (UNNAMED)\n");
ntfs_log_verbose("attribute name = \"\" (UNNAMED)\n");
else
mkDprintf("attribute name = \"%s\" (length %u Unicode "
ntfs_log_verbose("attribute name = \"%s\" (length %u Unicode "
"characters)\n", s2,
(unsigned int)attr_name_len);
@ -300,7 +271,7 @@ static void parse_options(int argc, char *argv[])
if (*s2 || ll < 0 || (ll >= LLONG_MAX && errno == ERANGE))
err_exit("Invalid new length: %s\n", s);
new_len = ll;
mkDprintf("new length = %lli\n", new_len);
ntfs_log_verbose("new length = %lli\n", new_len);
}
/**
@ -580,7 +551,7 @@ static void dump_attr_record(MFT_RECORD *m, ATTR_RECORD *a)
// printf("name = %c%c%c%c%c\n", *p, p[1], p[2], p[3], p[4]);
// }
if (ucstos(s, attr_defs[i].name, sizeof(s)) == -1) {
Eprintf("Could not convert Unicode string to single "
ntfs_log_error("Could not convert Unicode string to single "
"byte string in current locale.\n");
strncpy(s, "Error converting Unicode string",
sizeof(s));
@ -600,7 +571,7 @@ static void dump_attr_record(MFT_RECORD *m, ATTR_RECORD *a)
cpu_to_le16(a->name_offset)),
min((int)sizeof(s),
a->name_length + 1)) == -1) {
Eprintf("Could not convert Unicode string to single "
ntfs_log_error("Could not convert Unicode string to single "
"byte string in current locale.\n");
strncpy(s, "Error converting Unicode string",
sizeof(s));
@ -717,14 +688,13 @@ static void ntfstruncate_exit(void)
ntfs_attr_close(na);
/* Close the inode. */
if (ni && ntfs_inode_close(ni)) {
fprintf(stderr, "Warning: Failed to close inode %lli: %s\n",
(long long)inode, strerror(errno));
ntfs_log_perror("Warning: Failed to close inode %lli",
(long long)inode);
}
/* Unmount the volume. */
err = ntfs_umount(vol, 0);
if (err == -1)
fprintf(stderr, "Warning: Could not umount %s: %s\n", dev_name,
strerror(errno));
ntfs_log_perror("Warning: Could not umount %s", dev_name);
/* Free the attribute name if it exists. */
if (attr_name && attr_name != AT_UNNAMED)
free(attr_name);
@ -738,6 +708,8 @@ int main(int argc, char **argv)
unsigned long mnt_flags, ul;
int err;
ntfs_log_set_handler(ntfs_log_handler_outerr);
/* Initialize opts to zero / required values. */
memset(&opts, 0, sizeof(opts));
@ -754,10 +726,10 @@ int main(int argc, char **argv)
/* Make sure the file system is not mounted. */
if (ntfs_check_if_mounted(dev_name, &mnt_flags))
Eprintf("Failed to determine whether %s is mounted: %s\n",
dev_name, strerror(errno));
ntfs_log_perror("Failed to determine whether %s is mounted",
dev_name);
else if (mnt_flags & NTFS_MF_MOUNTED) {
Eprintf("%s is mounted.\n", dev_name);
ntfs_log_error("%s is mounted.\n", dev_name);
if (!opts.force)
err_exit("Refusing to run!\n");
fprintf(stderr, "ntfstruncate forced anyway. Hope /etc/mtab "
@ -766,7 +738,7 @@ int main(int argc, char **argv)
/* Mount the device. */
if (opts.no_action) {
Qprintf("Running in READ-ONLY mode!\n");
ntfs_log_quiet("Running in READ-ONLY mode!\n");
ul = MS_RDONLY;
} else
ul = 0;
@ -777,7 +749,7 @@ int main(int argc, char **argv)
/* Register our exit function which will unlock and close the device. */
err = atexit(&ntfstruncate_exit);
if (err == -1) {
Eprintf("Could not set up exit() function because atexit() "
ntfs_log_error("Could not set up exit() function because atexit() "
"failed: %s Aborting...\n", strerror(errno));
ntfstruncate_exit();
exit(1);
@ -796,7 +768,7 @@ int main(int argc, char **argv)
(unsigned int)attr_type, strerror(errno));
if (!opts.quiet && opts.verbose > 1) {
mkDprintf("Dumping mft record before calling "
ntfs_log_verbose("Dumping mft record before calling "
"ntfs_attr_truncate():\n");
dump_mft_record(ni->mrec);
}
@ -808,7 +780,7 @@ int main(int argc, char **argv)
(unsigned int)attr_type, strerror(errno));
if (!opts.quiet && opts.verbose > 1) {
mkDprintf("Dumping mft record after calling "
ntfs_log_verbose("Dumping mft record after calling "
"ntfs_attr_truncate():\n");
dump_mft_record(ni->mrec);
}
@ -826,8 +798,7 @@ int main(int argc, char **argv)
/* Unmount the volume. */
err = ntfs_umount(vol, 0);
if (err == -1)
fprintf(stderr, "Warning: Failed to umount %s: %s\n", dev_name,
strerror(errno));
ntfs_log_perror("Warning: Failed to umount %s", dev_name);
/* Free the attribute name if it exists. */
if (attr_name && attr_name != AT_UNNAMED)
@ -836,7 +807,7 @@ int main(int argc, char **argv)
/* Finally, disable our ntfstruncate_exit() handler. */
success = TRUE;
Qprintf("ntfstruncate completed successfully. Have a nice day.\n");
ntfs_log_quiet("ntfstruncate completed successfully. Have a nice day.\n");
return 0;
}