Moved general declarations from ntfsrecover.h to logfile.h

The declarations related to the log file structure are now grouped
in logfile.h, those specific to the recovery process are kept in
ntfsrecover.h
This commit is contained in:
Jean-Pierre André 2016-04-06 11:03:31 +02:00
parent 9693dd2fc1
commit 3cc22ba329
5 changed files with 112 additions and 255 deletions

View File

@ -2,6 +2,7 @@
* logfile.h - Exports for $LogFile handling. Originated from the Linux-NTFS project.
*
* Copyright (c) 2000-2005 Anton Altaparmakov
* Copyright (c) 2016 Jean-Pierre Andre
*
* This program/include file is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published
@ -102,8 +103,8 @@ typedef struct {
* in this particular client array. Also inside the client records themselves,
* this means that there are no client records preceding or following this one.
*/
#define LOGFILE_NO_CLIENT const_cpu_to_le16(0xffff)
#define LOGFILE_NO_CLIENT_CPU 0xffff
#define LOGFILE_NO_CLIENT const_cpu_to_le16(LOGFILE_NO_CLIENT_CPU)
/*
* These are the so far known RESTART_AREA_* flags (16-bit) which contain
@ -322,22 +323,23 @@ typedef struct {
le32 flags;
le16 page_count;
le16 page_position;
union {
struct {
le16 next_record_offset;
u8 reserved[6];
le16 reserved[3];
leLSN last_end_lsn;
} __attribute__((__packed__)) packed;
} __attribute__((__packed__)) header;
} __attribute__((__packed__)) RECORD_PAGE_HEADER;
/**
* enum LOG_RECORD_FLAGS - Possible 16-bit flags for log records.
*
* Some flags describe what kind of update is being logged.
*
* (Or is it log record pages?)
*/
typedef enum {
LOG_RECORD_MULTI_PAGE = const_cpu_to_le16(0x0001), /* ??? */
/* The flags below were introduced in Windows 10 */
LOG_RECORD_DELETING = const_cpu_to_le16(0x0002),
LOG_RECORD_ADDING = const_cpu_to_le16(0x0004),
LOG_RECORD_SIZE_PLACE_HOLDER = 0xffff,
/* This has nothing to do with the log record. It is only so
gcc knows to make the flags 16-bit. */
@ -351,6 +353,32 @@ typedef struct {
le16 client_index;
} __attribute__((__packed__)) LOG_CLIENT_ID;
/*
* LOG_RECORD_TYPE : types of log records
*/
enum {
LOG_STANDARD = const_cpu_to_le32(1),
LOG_CHECKPOINT = const_cpu_to_le32(2),
LOG_RECORD_TYPE_PLACE_HOLDER = 0xffffffffU
} ;
typedef le32 LOG_RECORD_TYPE;
/*
* ATTRIBUTE_FLAGS : flags describing the kind of NTFS record
* is being updated.
* These flags were introduced in Vista, only two flags are known?
*/
enum {
ACTS_ON_MFT = const_cpu_to_le16(2),
ACTS_ON_INDX = const_cpu_to_le16(8),
ATTRIBUTE_FLAGS_PLACE_HOLDER = 0xffff,
} ;
typedef le16 ATTRIBUTE_FLAGS;
#define LOG_RECORD_HEAD_SZ 0x30 /* size of header of struct LOG_RECORD */
/**
* struct LOG_RECORD - Log record header.
*
@ -362,15 +390,17 @@ typedef struct {
leLSN client_undo_next_lsn;
le32 client_data_length;
LOG_CLIENT_ID client_id;
le32 record_type;
LOG_RECORD_TYPE record_type;
le32 transaction_id;
le16 flags;
LOG_RECORD_FLAGS log_record_flags;
le16 reserved_or_alignment[3];
/* Now are at ofs 0x30 into struct. */
le16 redo_operation;
le16 undo_operation;
le16 redo_offset;
le16 redo_length;
union {
struct {
le16 undo_offset;
le16 undo_length;
le16 target_attribute;
@ -379,15 +409,60 @@ typedef struct {
/* Now at ofs 0x40. */
le16 record_offset;
le16 attribute_offset;
le32 alignment_or_reserved;
le16 cluster_index;
ATTRIBUTE_FLAGS attribute_flags;
leVCN target_vcn;
/* Now at ofs 0x50. */
struct { /* Only present if lcns_to_follow
leLCN lcn_list[0]; /* Only present if lcns_to_follow
is not 0. */
leLCN lcn;
} __attribute__((__packed__)) lcn_list[0];
} __attribute__((__packed__));
struct {
leLSN transaction_lsn;
leLSN attributes_lsn;
leLSN names_lsn;
leLSN dirty_pages_lsn;
le64 unknown_list[0];
} __attribute__((__packed__));
} __attribute__((__packed__));
} __attribute__((__packed__)) LOG_RECORD;
/**
* struct BITMAP_ACTION - Bitmap change being logged
*/
struct BITMAP_ACTION {
le32 firstbit;
le32 count;
} ;
/**
* struct ATTR - Attribute record.
*
* The format of an attribute record has changed from Windows 10.
* The old format was 44 bytes long, despite having 8 bytes fields,
* and this leads to alignment problems in arrays.
* This problem does not occur in the new format, which is shorter.
* The format being used can generally be determined from size.
*/
typedef struct { /* Format up to Win10 (44 bytes) */
le64 unknown1;
le64 unknown2;
le64 inode;
leLSN lsn;
le32 unknown3;
le32 type;
le32 unknown4;
} __attribute__((__packed__)) ATTR_OLD;
typedef struct { /* Format since Win10 (40 bytes) */
le64 unknown1;
le64 unknown2;
le32 type;
le32 unknown3;
le64 inode;
leLSN lsn;
} __attribute__((__packed__)) ATTR_NEW;
extern BOOL ntfs_check_logfile(ntfs_attr *log_na, RESTART_PAGE_HEADER **rp);
extern BOOL ntfs_is_logfile_clean(ntfs_attr *log_na, RESTART_PAGE_HEADER *rp);
extern int ntfs_empty_logfile(ntfs_attr *na);

View File

@ -557,17 +557,17 @@ static void dump_log_record(LOG_RECORD *lr)
(unsigned int)le32_to_cpu(lr->record_type));
ntfs_log_info("transaction_id = 0x%x\n",
(unsigned int)le32_to_cpu(lr->transaction_id));
ntfs_log_info("flags = 0x%x:", le16_to_cpu(lr->flags));
if (!lr->flags)
ntfs_log_info("flags = 0x%x:", le16_to_cpu(lr->log_record_flags));
if (!lr->log_record_flags)
ntfs_log_info(" NONE\n");
else {
int _b = 0;
if (lr->flags & LOG_RECORD_MULTI_PAGE) {
if (lr->log_record_flags & LOG_RECORD_MULTI_PAGE) {
ntfs_log_info(" LOG_RECORD_MULTI_PAGE");
_b = 1;
}
if (lr->flags & ~LOG_RECORD_MULTI_PAGE) {
if (lr->log_record_flags & ~LOG_RECORD_MULTI_PAGE) {
if (_b)
ntfs_log_info(" |");
ntfs_log_info(" Unknown flags");
@ -589,8 +589,8 @@ static void dump_log_record(LOG_RECORD *lr)
if (le16_to_cpu(lr->lcns_to_follow) > 0)
ntfs_log_info("Array of lcns:\n");
for (i = 0; i < le16_to_cpu(lr->lcns_to_follow); i++)
ntfs_log_info("lcn_list[%u].lcn = 0x%llx\n", i, (unsigned long long)
sle64_to_cpu(lr->lcn_list[i].lcn));
ntfs_log_info("lcn_list[%u].lcn = 0x%llx\n", i,
(unsigned long long)sle64_to_cpu(lr->lcn_list[i]));
}
/**
@ -633,9 +633,9 @@ rcrd_pass_loc:
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)
le16_to_cpu(rcrd->header.packed.next_record_offset));
le16_to_cpu(rcrd->next_record_offset));
ntfs_log_info("header.last_end_lsn = 0x%llx\n", (unsigned long long)
sle64_to_cpu(rcrd->header.packed.last_end_lsn));
sle64_to_cpu(rcrd->last_end_lsn));
/*
* Where does the 0x40 come from? Is it just usa_offset +
* usa_client * 2 + 7 & ~7 or is it derived from somewhere?
@ -648,7 +648,7 @@ rcrd_pass_loc:
client++;
lr = (LOG_RECORD*)((u8*)lr + 0x70);
} while (((u8*)lr + 0x70 <= (u8*)rcrd +
le16_to_cpu(rcrd->header.packed.next_record_offset)));
le16_to_cpu(rcrd->next_record_offset)));
pass++;
goto rcrd_pass_loc;

View File

@ -1,7 +1,7 @@
/*
* Process log data from an NTFS partition
*
* Copyright (c) 2012-2015 Jean-Pierre Andre
* Copyright (c) 2012-2016 Jean-Pierre Andre
*
* This program examines the Windows log file of an ntfs partition
* and plays the committed transactions in order to restore the
@ -101,6 +101,7 @@
#include "volume.h"
#include "unistr.h"
#include "mst.h"
#include "logfile.h"
#include "ntfsrecover.h"
#include "utils.h"
#include "misc.h"
@ -3832,7 +3833,7 @@ static void version(void)
{
printf("\n%s v%s (libntfs-3g) - Recover updates committed by Windows"
" on an NTFS Volume.\n\n", "ntfsrecover", VERSION);
printf("Copyright (c) 2012-2015 Jean-Pierre Andre\n");
printf("Copyright (c) 2012-2016 Jean-Pierre Andre\n");
printf("\n%s\n%s%s\n", ntfs_gpl, ntfs_bugs, ntfs_home);
}
@ -3856,7 +3857,6 @@ static void usage(void)
fprintf(stderr," -u : undo the latest count transaction sets\n");
fprintf(stderr," -v : show more information (-vv yet more)\n");
fprintf(stderr," -V : show version and exit\n");
fprintf(stderr," Copyright (c) 2012-2015 Jean-Pierre Andre\n");
}
/*

View File

@ -2,7 +2,7 @@
* Declarations for processing log data
*
* Copyright (c) 2000-2005 Anton Altaparmakov
* Copyright (c) 2014-2015 Jean-Pierre Andre
* Copyright (c) 2014-2016 Jean-Pierre Andre
*/
/*
@ -22,16 +22,6 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
* TODO
* This file partially duplicates logfile.h (with modifications).
* The generic declarations are to be moved to logfile.h, thus
* implying adapting (at least) libntfs-3g/logfile.c and
* ntfsprogs/ntfsdump_logfile.c, and the declarations specific to
* ntfsrecover should be kept in this file.
* (removing ntfsdump_logfile.c might also be considered).
*/
#define getle16(p,x) le16_to_cpu(*(const le16*)((const char*)(p) + (x)))
#define getle32(p,x) le32_to_cpu(*(const le32*)((const char*)(p) + (x)))
#define getle64(p,x) le64_to_cpu(*(const le64*)((const char*)(p) + (x)))
@ -40,30 +30,6 @@
#define feedle32(p,x) (*(const le32*)((const char*)(p) + (x)))
#define feedle64(p,x) (*(const le64*)((const char*)(p) + (x)))
/*
* LOG_RECORD_TYPE : types of log records
*/
enum {
LOG_STANDARD = const_cpu_to_le32(1),
LOG_CHECKPOINT = const_cpu_to_le32(2),
LOG_RECORD_TYPE_PLACE_HOLDER = 0xffffffffU
} ;
typedef le32 LOG_RECORD_TYPE;
/*
* ATTRIBUTE_FLAGS : flags describing the kind of NTFS record
* is being updated.
* These flags were introduced in Vista, only two flags are known?
*/
enum {
ACTS_ON_MFT = const_cpu_to_le16(2),
ACTS_ON_INDX = const_cpu_to_le16(8),
ATTRIBUTE_FLAGS_PLACE_HOLDER = 0xffff,
} ;
typedef le16 ATTRIBUTE_FLAGS;
enum ACTIONS {
Noop, /* 0 */
CompensationlogRecord, /* 1 */
@ -106,157 +72,6 @@ enum ACTIONS {
LastAction /* 38 */
} ;
/**
* enum LOG_RECORD_FLAGS - Possible 16-bit flags for log records.
*
* Some flags describe what kind of update is being logged.
*
* (Or is it log record pages?)
*/
typedef enum {
LOG_RECORD_MULTI_PAGE = const_cpu_to_le16(0x0001), /* ??? */
/* The flags below were introduced in Windows 10 */
LOG_RECORD_DELETING = const_cpu_to_le16(0x0002),
LOG_RECORD_ADDING = const_cpu_to_le16(0x0004),
LOG_RECORD_SIZE_PLACE_HOLDER = 0xffff,
/* This has nothing to do with the log record. It is only so
gcc knows to make the flags 16-bit. */
} __attribute__((__packed__)) LOG_RECORD_FLAGS;
#define LOGFILE_NO_CLIENT const_cpu_to_le16(0xffff)
#define RESTART_VOLUME_IS_CLEAN const_cpu_to_le16(0x0002)
/* ntfsdoc p 39 (47), not in layout.h */
typedef struct { /* size 32 */
NTFS_RECORD_TYPES magic;
le16 usa_ofs;
le16 usa_count;
leLSN chkdsk_lsn;
le32 system_page_size;
le32 log_page_size;
le16 restart_area_offset;
le16 minor_ver;
le16 major_ver;
le16 usn;
} __attribute__((__packed__)) RESTART_PAGE_HEADER;
/* ntfsdoc p 40 (48), not in layout.h */
typedef struct { /* size 44 */
leLSN current_lsn;
le16 log_clients;
le16 client_free_list;
le16 client_in_use_list;
le16 flags;
le32 seq_number_bits;
le16 restart_area_length;
le16 client_array_offset;
le64 file_size;
le32 last_lsn_data_length;
le16 log_record_header_length;
le16 log_page_data_offset;
le32 restart_log_open_count;
le32 reserved;
} __attribute__((__packed__)) RESTART_AREA;
typedef struct { /* size 160 */
/*Ofs*/
/* 0*/ leLSN oldest_lsn; /* Oldest LSN needed by this client. On create
set to 0. */
/* 8*/ leLSN client_restart_lsn;/* LSN at which this client needs to restart
the volume, i.e. the current position within
the log file. At present, if clean this
should = current_lsn in restart area but it
probably also = current_lsn when dirty most
of the time. At create set to 0. */
/* 16*/ le16 prev_client; /* The offset to the previous log client record
in the array of log client records.
LOGFILE_NO_CLIENT means there is no previous
client record, i.e. this is the first one.
This is always LOGFILE_NO_CLIENT. */
/* 18*/ le16 next_client; /* The offset to the next log client record in
the array of log client records.
LOGFILE_NO_CLIENT means there are no next
client records, i.e. this is the last one.
This is always LOGFILE_NO_CLIENT. */
/* 20*/ le16 seq_number; /* On Win2k and presumably earlier, this is set
to zero every time the logfile is restarted
and it is incremented when the logfile is
closed at dismount time. Thus it is 0 when
dirty and 1 when clean. On WinXP and
presumably later, this is always 0. */
/* 22*/ u8 reserved[6]; /* Reserved/alignment. */
/* 28*/ le32 client_name_length;/* Length of client name in bytes. Should
always be 8. */
/* 32*/ le16 client_name[64]; /* Name of the client in Unicode. Should
always be "NTFS" with the remaining bytes
set to 0. */
/* sizeof() = 160 (0xa0) bytes */
} __attribute__((__packed__)) LOG_CLIENT_RECORD;
/* ntfsdoc p 41 (49), not in layout.h */
typedef struct { /* size 40 */
NTFS_RECORD_TYPES magic;
le16 usa_ofs;
le16 usa_count;
union {
leLSN last_lsn;
sle64 file_offset;
} __attribute__((__packed__)) copy;
le32 flags;
le16 page_count;
le16 page_position;
le16 next_record_offset;
le16 reserved[3];
leLSN last_end_lsn;
} __attribute__((__packed__)) RECORD_PAGE_HEADER;
/* ntfsdoc p 42 (50), not in layout.h */
#define LOG_RECORD_HEAD_SZ 0x30 /* size of header of struct LOG_RECORD */
typedef struct { /* size 80 */
leLSN this_lsn;
leLSN client_previous_lsn;
leLSN client_undo_next_lsn;
le32 client_data_length;
struct {
le16 seq_number;
le16 client_index;
} __attribute__((__packed__)) client_id;
LOG_RECORD_TYPE record_type;
le32 transaction_id;
LOG_RECORD_FLAGS log_record_flags;
le16 reserved_or_alignment[3];
le16 redo_operation;
le16 undo_operation;
le16 redo_offset;
le16 redo_length;
union {
struct {
le16 undo_offset;
le16 undo_length;
le16 target_attribute;
le16 lcns_to_follow;
le16 record_offset;
le16 attribute_offset;
le16 cluster_index;
ATTRIBUTE_FLAGS attribute_flags;
leVCN target_vcn;
le64 lcn_list[0];
} __attribute__((__packed__));
struct {
leLSN transaction_lsn;
leLSN attributes_lsn;
leLSN names_lsn;
leLSN dirty_pages_lsn;
le64 unknown_list[0];
} __attribute__((__packed__));
} __attribute__((__packed__));
} __attribute__((__packed__)) LOG_RECORD;
struct BUFFER {
unsigned int num;
unsigned int size;
@ -290,39 +105,6 @@ struct ATTR {
le16 name[1];
} ;
struct BITMAP_ACTION {
le32 firstbit;
le32 count;
} ;
/**
* struct ATTR - Attribute record.
*
* The format of an attribute record has changed from Windows 10.
* The old format was 44 bytes long, despite having 8 bytes fields,
* and this leads to alignment problems in arrays.
* This problem does not occur in the new format, which is shorter.
* The format being used can generally be determined from size.
*/
typedef struct { /* Format up to Win10 (44 bytes) */
le64 unknown1;
le64 unknown2;
le64 inode;
leLSN lsn;
le32 unknown3;
le32 type;
le32 unknown4;
} __attribute__((__packed__)) ATTR_OLD;
typedef struct { /* Format since Win10 (40 bytes) */
le64 unknown1;
le64 unknown2;
le32 type;
le32 unknown3;
le64 inode;
leLSN lsn;
} __attribute__((__packed__)) ATTR_NEW;
extern u32 clustersz;
extern int clusterbits;
extern u32 blocksz;
@ -364,7 +146,6 @@ u32 get_extra_offset(const LOG_RECORD *logr);
BOOL exception(int num);
struct STORE;
BOOL ntfs_check_logfile(ntfs_attr *log_na, RESTART_PAGE_HEADER **rp);
extern int play_undos(ntfs_volume *vol, const struct ACTION_RECORD *firstundo);
extern int play_redos(ntfs_volume *vol, const struct ACTION_RECORD *firstredo);
extern void show_redos(void);

View File

@ -1,7 +1,7 @@
/*
* Redo or undo a list of logged actions
*
* Copyright (c) 2014-2015 Jean-Pierre Andre
* Copyright (c) 2014-2016 Jean-Pierre Andre
*
*/
@ -67,6 +67,7 @@
#include "volume.h"
#include "unistr.h"
#include "mst.h"
#include "logfile.h"
#include "ntfsrecover.h"
#include "misc.h"