Subdivided the replay functions in playlog

Partially unnested play_redos() and play_undos()
This commit is contained in:
Jean-Pierre André 2015-11-12 15:44:47 +01:00
parent fe3e16243a
commit 22b59548d9

View File

@ -4234,38 +4234,25 @@ static int distribute_redos(ntfs_volume *vol,
return (err);
}
/*
* Play the redo actions from earliest to latest
*
* Currently we can only redo the last undone transaction,
* otherwise the attribute table would be out of phase.
*/
int play_redos(ntfs_volume *vol, const struct ACTION_RECORD *firstaction)
int play_one_redo(ntfs_volume *vol, const struct ACTION_RECORD *action)
{
const struct ACTION_RECORD *action;
MFT_RECORD *entry;
INDEX_BLOCK *indx;
char *buffer;
s64 this_lsn;
s64 data_lsn;
u32 xsize;
u16 rop;
u16 uop;
int err;
BOOL warn;
BOOL executed;
enum ACTION_KIND kind;
u16 rop;
u16 uop;
err = 0;
action = firstaction;
while (action && !err) {
this_lsn = le64_to_cpu(action->record.this_lsn);
/* Only committed actions should be redone */
if ((!optc || within_lcn_range(&action->record))
&& (action->flags & ACTION_TO_REDO)) {
rop = le16_to_cpu(action->record.redo_operation);
uop = le16_to_cpu(action->record.undo_operation);
this_lsn = le64_to_cpu(action->record.this_lsn);
if (optv)
printf("Redo action %d %s (%s) 0x%llx\n",
action->num,
@ -4364,17 +4351,14 @@ printf("** %s (action %d) not acting on MFT\n",actionname(rop),(int)action->num)
* have a stale lsn (consequence
* of ntfs-3g resetting the log)
*/
executed = ((s64)(data_lsn
- this_lsn) >= 0)
&& (((s64)(data_lsn
- latest_lsn)) <= 0)
executed = ((s64)(data_lsn - this_lsn) >= 0)
&& (((s64)(data_lsn - latest_lsn)) <= 0)
&& !exception(action->num);
} else {
if (!warn) {
/* Old record not needed */
if (!buffer)
buffer =
(char*)malloc(mftrecsz);
buffer = (char*)calloc(1, mftrecsz);
if (buffer)
executed = FALSE;
else
@ -4409,17 +4393,14 @@ printf("** %s (action %d) not acting on INDX\n",actionname(rop),(int)action->num
* have a stale lsn (consequence
* of ntfs-3g resetting the log)
*/
executed = ((s64)(data_lsn
- this_lsn) >= 0)
&& (((s64)(data_lsn
- latest_lsn)) <= 0)
executed = ((s64)(data_lsn - this_lsn) >= 0)
&& (((s64)(data_lsn - latest_lsn)) <= 0)
&& ! exception(action->num);
} else {
if (!warn) {
/* Old record not needed */
if (!buffer)
buffer =
(char*)malloc(xsize);
buffer = (char*)calloc(1, xsize);
if (buffer)
executed = FALSE;
else
@ -4435,8 +4416,7 @@ printf("** %s (action %d) not acting on INDX\n",actionname(rop),(int)action->num
break;
case ON_RAW :
if (action->record.attribute_flags
& (const_cpu_to_le16(
ACTS_ON_INDX | ACTS_ON_MFT))) {
& (const_cpu_to_le16(ACTS_ON_INDX | ACTS_ON_MFT))) {
printf("** Error : action %s on MFT"
" or INDX\n",
actionname(rop));
@ -4463,7 +4443,29 @@ printf("** %s (action %d) not acting on INDX\n",actionname(rop),(int)action->num
}
if (buffer)
free(buffer);
return (err);
}
/*
* Play the redo actions from earliest to latest
*
* Currently we can only redo the last undone transaction,
* otherwise the attribute table would be out of phase.
*/
int play_redos(ntfs_volume *vol, const struct ACTION_RECORD *firstaction)
{
const struct ACTION_RECORD *action;
int err;
err = 0;
action = firstaction;
while (action && !err) {
/* Only committed actions should be redone */
if ((!optc || within_lcn_range(&action->record))
&& (action->flags & ACTION_TO_REDO))
err = play_one_redo(vol, action);
if (!err)
action = action->next;
}
@ -4616,19 +4618,8 @@ static int distribute_undos(ntfs_volume *vol, const struct ACTION_RECORD *action
return (err);
}
/*
* Play the undo actions from latest to earliest
*
* For structured record, a check is made on the lsn to only
* try to undo the actions which were executed. This implies
* identifying actions on a structured record.
*
* Returns 0 if successful
*/
int play_undos(ntfs_volume *vol, const struct ACTION_RECORD *lastaction)
int play_one_undo(ntfs_volume *vol, const struct ACTION_RECORD *action)
{
const struct ACTION_RECORD *action;
MFT_RECORD *entry;
INDEX_BLOCK *indx;
char *buffer;
@ -4640,9 +4631,6 @@ int play_undos(ntfs_volume *vol, const struct ACTION_RECORD *lastaction)
enum ACTION_KIND kind;
err = 0;
action = lastaction;
while (action && !err) {
if (!optc || within_lcn_range(&action->record)) {
rop = le16_to_cpu(action->record.redo_operation);
uop = le16_to_cpu(action->record.undo_operation);
if (optv)
@ -4724,8 +4712,7 @@ int play_undos(ntfs_volume *vol, const struct ACTION_RECORD *lastaction)
if (!(action->record.attribute_flags & const_cpu_to_le16(ACTS_ON_MFT)))
printf("** %s (action %d) not acting on MFT\n",actionname(rop),(int)action->num);
*/
buffer = read_protected(vol, &action->record,
mftrecsz, TRUE);
buffer = read_protected(vol, &action->record, mftrecsz, TRUE);
entry = (MFT_RECORD*)buffer;
if (entry) {
if (entry->magic == magic_FILE) {
@ -4741,16 +4728,15 @@ printf("record lsn 0x%llx is %s than action %d lsn 0x%llx\n",
(int)action->num,
(long long)le64_to_cpu(action->record.this_lsn));
} else {
printf("** %s (action %d) not"
" acting on MFT\n",
actionname(rop),
(int)action->num);
printf("** %s (action %d) not acting on MFT\n",
actionname(rop), (int)action->num);
err = 1;
}
} else {
/* Undoing a record create which was not done ? */
// TODO make sure this is about a newly allocated record (with bad fixup)
// TODO check this is inputting a full record (record lth == data lth)
buffer = (char*)malloc(mftrecsz);
buffer = (char*)calloc(1, mftrecsz);
}
break;
case ON_INDX :
@ -4760,8 +4746,7 @@ if (!(action->record.attribute_flags & const_cpu_to_le16(ACTS_ON_INDX)))
printf("** %s (action %d) not acting on INDX\n",actionname(rop),(int)action->num);
*/
xsize = vol->indx_record_size;
buffer = read_protected(vol, &action->record,
xsize, TRUE);
buffer = read_protected(vol, &action->record, xsize, TRUE);
indx = (INDEX_BLOCK*)buffer;
if (indx) {
if (indx->magic == magic_INDX) {
@ -4777,27 +4762,24 @@ printf("index lsn 0x%llx is %s than action %d lsn 0x%llx\n",
(int)action->num,
(long long)le64_to_cpu(action->record.this_lsn));
} else {
printf("** %s (action %d) not"
" acting on INDX\n",
actionname(rop),
(int)action->num);
printf("** %s (action %d) not acting on INDX\n",
actionname(rop), (int)action->num);
err = 1;
}
} else {
/* Undoing a record create which was not done ? */
// TODO make sure this is about a newly allocated record (with bad fixup)
// TODO check this is inputting a full record (record lth == data lth)
// recreate an INDX record if this is the first entry
buffer = (char*)malloc(xsize);
buffer = (char*)calloc(1, xsize);
err = create_indx(vol, action, buffer);
executed = TRUE;
}
break;
case ON_RAW :
if (action->record.attribute_flags
& (const_cpu_to_le16(
ACTS_ON_INDX | ACTS_ON_MFT))) {
printf("** Error : action %s on MFT"
" or INDX\n",
& (const_cpu_to_le16(ACTS_ON_INDX | ACTS_ON_MFT))) {
printf("** Error : action %s on MFT or INDX\n",
actionname(rop));
err = 1;
} else {
@ -4818,7 +4800,30 @@ printf("index lsn 0x%llx is %s than action %d lsn 0x%llx\n",
}
if (buffer)
free(buffer);
return (err);
}
/*
* Play the undo actions from latest to earliest
*
* For structured record, a check is made on the lsn to only
* try to undo the actions which were executed. This implies
* identifying actions on a structured record.
*
* Returns 0 if successful
*/
int play_undos(ntfs_volume *vol, const struct ACTION_RECORD *lastaction)
{
const struct ACTION_RECORD *action;
int err;
err = 0;
action = lastaction;
while (action && !err) {
if (!optc || within_lcn_range(&action->record))
err = play_one_undo(vol, action);
if (!err)
action = action->prev;
}