"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "ntfsprogs/playlog.c" between
ntfs-3g_ntfsprogs-2016.2.22.tgz and ntfs-3g_ntfsprogs-2017.3.23.tgz

About: NTFS-3G is a read-write NTFS driver for Linux and other operating systems. It provides safe handling of the Windows XP, Windows Server 2003, Windows 2000, Windows Vista, Windows Server 2008, Windows 7 and Windows 8 NTFS file systems.

playlog.c  (ntfs-3g_ntfsprogs-2016.2.22.tgz):playlog.c  (ntfs-3g_ntfsprogs-2017.3.23.tgz)
/* /*
* Redo or undo a list of logged actions * Redo or undo a list of logged actions
* *
* Copyright (c) 2014-2015 Jean-Pierre Andre * Copyright (c) 2014-2016 Jean-Pierre Andre
* *
*/ */
/* /*
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or * the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
skipping to change at line 70 skipping to change at line 70
#include "logging.h" #include "logging.h"
#include "runlist.h" #include "runlist.h"
#include "mft.h" #include "mft.h"
#include "inode.h" #include "inode.h"
#include "attrib.h" #include "attrib.h"
#include "bitmap.h" #include "bitmap.h"
#include "index.h" #include "index.h"
#include "volume.h" #include "volume.h"
#include "unistr.h" #include "unistr.h"
#include "mst.h" #include "mst.h"
#include "logfile.h"
#include "ntfsrecover.h" #include "ntfsrecover.h"
#include "misc.h" #include "misc.h"
struct STORE { struct STORE {
struct STORE *upper; struct STORE *upper;
struct STORE *lower; struct STORE *lower;
LCN lcn; LCN lcn;
char data[1]; char data[1];
} ; } ;
skipping to change at line 120 skipping to change at line 121
if (s[i] == *p) { if (s[i] == *p) {
j = 1; j = 1;
while ((j < m) && (s[i + j] == p[j])) while ((j < m) && (s[i + j] == p[j]))
j++; j++;
if (j == m) if (j == m)
printf("=== found at offset 0x%x %d\n",i,i); printf("=== found at offset 0x%x %d\n",i,i);
} }
} }
*/ */
static u64 inode_number(const struct LOG_RECORD *logr) static u64 inode_number(const LOG_RECORD *logr)
{ {
u64 offset; u64 offset;
offset = ((u64)le32_to_cpu(logr->target_vcn) offset = ((u64)sle64_to_cpu(logr->target_vcn)
<< clusterbits) << clusterbits)
+ ((u32)le16_to_cpu(logr->cluster_index) + ((u32)le16_to_cpu(logr->cluster_index)
<< NTFS_BLOCK_SIZE_BITS); << NTFS_BLOCK_SIZE_BITS);
return (offset >> mftrecbits); return (offset >> mftrecbits);
} }
/* /*
* Find an in-memory copy of a needed cluster * Find an in-memory copy of a needed cluster
* *
* Optionally, allocate a copy. * Optionally, allocate a copy.
skipping to change at line 411 skipping to change at line 412
return (err); return (err);
} }
/* /*
* Allocate a buffer and read a full set of raw clusters * Allocate a buffer and read a full set of raw clusters
* *
* Do not use for accessing $LogFile. * Do not use for accessing $LogFile.
* With option -n reading is first attempted from the memory store * With option -n reading is first attempted from the memory store
*/ */
static char *read_raw(ntfs_volume *vol, const struct LOG_RECORD *logr) static char *read_raw(ntfs_volume *vol, const LOG_RECORD *logr)
{ {
char *buffer; char *buffer;
char *target; char *target;
struct STORE *store; struct STORE *store;
LCN lcn; LCN lcn;
int count; int count;
int i; int i;
BOOL fail; BOOL fail;
count = le16_to_cpu(logr->lcns_to_follow); count = le16_to_cpu(logr->lcns_to_follow);
if (!count) { if (!count) {
printf("** Error : no lcn to read from\n"); printf("** Error : no lcn to read from\n");
buffer = (char*)NULL; buffer = (char*)NULL;
} else } else
buffer = (char*)malloc(clustersz*count); buffer = (char*)malloc(clustersz*count);
// TODO error messages // TODO error messages
if (buffer) { if (buffer) {
fail = FALSE; fail = FALSE;
for (i=0; (i<count) && !fail; i++) { for (i=0; (i<count) && !fail; i++) {
store = (struct STORE*)NULL; store = (struct STORE*)NULL;
lcn = le64_to_cpu(logr->lcn_list[i]); lcn = sle64_to_cpu(logr->lcn_list[i]);
target = buffer + clustersz*i; target = buffer + clustersz*i;
if (optn) { if (optn) {
store = getclusterentry(lcn, FALSE); store = getclusterentry(lcn, FALSE);
if (store) { if (store) {
memcpy(target, store->data, clustersz); memcpy(target, store->data, clustersz);
if (optv) if (optv)
printf("== lcn 0x%llx from store\n", printf("== lcn 0x%llx from store\n",
(long long)lcn); (long long)lcn);
if ((optv > 1) && optc if ((optv > 1) && optc
&& within_lcn_range(logr)) && within_lcn_range(logr))
skipping to change at line 479 skipping to change at line 480
return (buffer); return (buffer);
} }
/* /*
* Write a full set of raw clusters * Write a full set of raw clusters
* *
* Do not use for accessing $LogFile. * Do not use for accessing $LogFile.
* With option -n a copy of the buffer is kept in memory for later use. * With option -n a copy of the buffer is kept in memory for later use.
*/ */
static int write_raw(ntfs_volume *vol, const struct LOG_RECORD *logr, static int write_raw(ntfs_volume *vol, const LOG_RECORD *logr,
char *buffer) char *buffer)
{ {
int err; int err;
struct STORE *store; struct STORE *store;
LCN lcn; LCN lcn;
char *source; char *source;
int count; int count;
int i; int i;
err = 0; err = 0;
count = le16_to_cpu(logr->lcns_to_follow); count = le16_to_cpu(logr->lcns_to_follow);
if (!count) if (!count)
printf("** Error : no lcn to write to\n"); printf("** Error : no lcn to write to\n");
if (optn) { if (optn) {
for (i=0; (i<count) && !err; i++) { for (i=0; (i<count) && !err; i++) {
lcn = le64_to_cpu(logr->lcn_list[i]); lcn = sle64_to_cpu(logr->lcn_list[i]);
source = buffer + clustersz*i; source = buffer + clustersz*i;
store = getclusterentry(lcn, TRUE); store = getclusterentry(lcn, TRUE);
if (store) { if (store) {
memcpy(store->data, source, clustersz); memcpy(store->data, source, clustersz);
if (optv) if (optv)
printf("== lcn 0x%llx to store\n", printf("== lcn 0x%llx to store\n",
(long long)lcn); (long long)lcn);
if ((optv > 1) && optc if ((optv > 1) && optc
&& within_lcn_range(logr)) && within_lcn_range(logr))
dump(store->data, clustersz); dump(store->data, clustersz);
} else { } else {
printf("** Could not store cluster 0x%llx\n", printf("** Could not store cluster 0x%llx\n",
(long long)lcn); (long long)lcn);
err = 1; err = 1;
} }
} }
} else { } else {
for (i=0; (i<count) && !err; i++) { for (i=0; (i<count) && !err; i++) {
lcn = le64_to_cpu(logr->lcn_list[i]); lcn = sle64_to_cpu(logr->lcn_list[i]);
if (optv) if (optv)
printf("== lcn 0x%llx to device\n", printf("== lcn 0x%llx to device\n",
(long long)lcn); (long long)lcn);
source = buffer + clustersz*i; source = buffer + clustersz*i;
if (ntfs_pwrite(vol->dev, lcn << clusterbits, if (ntfs_pwrite(vol->dev, lcn << clusterbits,
clustersz, source) != clustersz) { clustersz, source) != clustersz) {
printf("** Could not write cluster 0x%llx\n", printf("** Could not write cluster 0x%llx\n",
(long long)lcn); (long long)lcn);
err = 1; err = 1;
} }
} }
} }
return (err); return (err);
} }
/* /*
* Write a full set of raw clusters to mft_mirr * Write a full set of raw clusters to mft_mirr
*/ */
static int write_mirr(ntfs_volume *vol, const struct LOG_RECORD *logr, static int write_mirr(ntfs_volume *vol, const LOG_RECORD *logr,
char *buffer) char *buffer)
{ {
int err; int err;
LCN lcn; LCN lcn;
char *source; char *source;
int count; int count;
int i; int i;
err = 0; err = 0;
count = le16_to_cpu(logr->lcns_to_follow); count = le16_to_cpu(logr->lcns_to_follow);
if (!count) if (!count)
printf("** Error : no lcn to write to\n"); printf("** Error : no lcn to write to\n");
if (!optn) { if (!optn) {
for (i=0; (i<count) && !err; i++) { for (i=0; (i<count) && !err; i++) {
lcn = ntfs_attr_vcn_to_lcn(vol->mftmirr_na, lcn = ntfs_attr_vcn_to_lcn(vol->mftmirr_na,
le32_to_cpu(logr->target_vcn) + i); sle64_to_cpu(logr->target_vcn) + i);
source = buffer + clustersz*i; source = buffer + clustersz*i;
if ((lcn < 0) if ((lcn < 0)
|| (ntfs_pwrite(vol->dev, lcn << clusterbits, || (ntfs_pwrite(vol->dev, lcn << clusterbits,
clustersz, source) != clustersz)) { clustersz, source) != clustersz)) {
printf("** Could not write cluster 0x%llx\n", printf("** Could not write cluster 0x%llx\n",
(long long)lcn); (long long)lcn);
err = 1; err = 1;
} }
} }
} }
return (err); return (err);
} }
/* /*
* Allocate a buffer and read a single protected record * Allocate a buffer and read a single protected record
*/ */
static char *read_protected(ntfs_volume *vol, const struct LOG_RECORD *logr, static char *read_protected(ntfs_volume *vol, const LOG_RECORD *logr,
u32 size, BOOL warn) u32 size, BOOL warn)
{ {
char *buffer; char *buffer;
char *full; char *full;
u32 pos; u32 pos;
LCN lcn; LCN lcn;
/* read full clusters */ /* read full clusters */
buffer = read_raw(vol, logr); buffer = read_raw(vol, logr);
/* /*
skipping to change at line 595 skipping to change at line 596
if (buffer) { if (buffer) {
pos = le16_to_cpu(logr->cluster_index) pos = le16_to_cpu(logr->cluster_index)
<< NTFS_BLOCK_SIZE_BITS; << NTFS_BLOCK_SIZE_BITS;
memcpy(buffer, full + pos, size); memcpy(buffer, full + pos, size);
} }
free(full); free(full);
} }
if (buffer && (ntfs_mst_post_read_fixup_warn( if (buffer && (ntfs_mst_post_read_fixup_warn(
(NTFS_RECORD*)buffer, size, FALSE) < 0)) { (NTFS_RECORD*)buffer, size, FALSE) < 0)) {
if (warn) { if (warn) {
lcn = le64_to_cpu(logr->lcn_list[0]); lcn = sle64_to_cpu(logr->lcn_list[0]);
printf("** Invalid protected record at 0x%llx" printf("** Invalid protected record at 0x%llx"
" index %d\n", " index %d\n",
(long long)lcn, (long long)lcn,
(int)le16_to_cpu(logr->cluster_index)); (int)le16_to_cpu(logr->cluster_index));
} }
free(buffer); free(buffer);
buffer = (char*)NULL; buffer = (char*)NULL;
} }
return (buffer); return (buffer);
} }
/* /*
* Protect a single record, write, and deallocate the buffer * Protect a single record, write, and deallocate the buffer
* *
* With option -n a copy of the buffer is kept in protected form in * With option -n a copy of the buffer is kept in protected form in
* memory for later use. * memory for later use.
* As the store only knows about clusters, if the record is smaller * As the store only knows about clusters, if the record is smaller
* than a cluster, have to read, merge and write. * than a cluster, have to read, merge and write.
*/ */
static int write_protected(ntfs_volume *vol, const struct LOG_RECORD *logr, static int write_protected(ntfs_volume *vol, const LOG_RECORD *logr,
char *buffer, u32 size) char *buffer, u32 size)
{ {
MFT_RECORD *record; MFT_RECORD *record;
INDEX_BLOCK *indx; INDEX_BLOCK *indx;
char *full; char *full;
u32 pos; u32 pos;
BOOL mftmirr; BOOL mftmirr;
BOOL checked; BOOL checked;
int err; int err;
skipping to change at line 642 skipping to change at line 643
if (optv) if (optv)
printf("update inode %ld lsn 0x%llx" printf("update inode %ld lsn 0x%llx"
" (record %s than action 0x%llx)\n", " (record %s than action 0x%llx)\n",
(long)le32_to_cpu(record->mft_record_number), (long)le32_to_cpu(record->mft_record_number),
(long long)sle64_to_cpu(record->lsn), (long long)sle64_to_cpu(record->lsn),
((s64)(sle64_to_cpu(record->lsn) ((s64)(sle64_to_cpu(record->lsn)
- sle64_to_cpu(logr->this_lsn)) < 0 ? - sle64_to_cpu(logr->this_lsn)) < 0 ?
"older" : "newer"), "older" : "newer"),
(long long)sle64_to_cpu(logr->this_lsn)); (long long)sle64_to_cpu(logr->this_lsn));
if (optv > 1) if (optv > 1)
printf("mft vcn %ld index %d\n", printf("mft vcn %lld index %d\n",
(long)le32_to_cpu(logr->target_vcn), (long long)sle64_to_cpu(logr->target_vcn),
(int)le16_to_cpu(logr->cluster_index)); (int)le16_to_cpu(logr->cluster_index));
err = sanity_mft(buffer); err = sanity_mft(buffer);
/* Should set to some previous lsn for undos */ /* Should set to some previous lsn for undos */
if (opts) if (opts)
record->lsn = logr->this_lsn; record->lsn = logr->this_lsn;
/* Duplicate on mftmirr if not overflowing its size */ /* Duplicate on mftmirr if not overflowing its size */
mftmirr = (((u64)le32_to_cpu(logr->target_vcn) mftmirr = (((u64)sle64_to_cpu(logr->target_vcn)
+ le16_to_cpu(logr->lcns_to_follow)) + le16_to_cpu(logr->lcns_to_follow))
<< clusterbits) << clusterbits)
<= (((u64)vol->mftmirr_size) << mftrecbits); <= (((u64)vol->mftmirr_size) << mftrecbits);
checked = TRUE; checked = TRUE;
} }
if ((size == vol->indx_record_size) && !memcmp(buffer,"INDX",4)) { if ((size == vol->indx_record_size) && !memcmp(buffer,"INDX",4)) {
indx = (INDEX_BLOCK*)buffer; indx = (INDEX_BLOCK*)buffer;
if (optv) if (optv)
printf("update index lsn 0x%llx" printf("update index lsn 0x%llx"
" (index %s than action 0x%llx)\n", " (index %s than action 0x%llx)\n",
skipping to change at line 859 skipping to change at line 860
LCN lcn; LCN lcn;
ATTR_RECORD *attr; ATTR_RECORD *attr;
u32 attrend; u32 attrend;
int err; int err;
int changed; int changed;
err = 1; err = 1;
if (action->record.undo_length != action->record.redo_length) if (action->record.undo_length != action->record.redo_length)
printf("** Error size change in change_resident\n"); printf("** Error size change in change_resident\n");
if (optv > 1) { if (optv > 1) {
lcn = le64_to_cpu(action->record.lcn_list[0]); lcn = sle64_to_cpu(action->record.lcn_list[0]);
printf("-> inode %lld lcn 0x%llx target 0x%x length %d\n", printf("-> inode %lld lcn 0x%llx target 0x%x length %d\n",
(long long)inode_number(&action->record), (long long)inode_number(&action->record),
(long long)lcn, (int)target, (int)length); (long long)lcn, (int)target, (int)length);
} }
attr = (ATTR_RECORD*)(buffer attr = (ATTR_RECORD*)(buffer
+ le16_to_cpu(action->record.record_offset)); + le16_to_cpu(action->record.record_offset));
if (optv > 1) { if (optv > 1) {
printf("-> existing record :\n"); printf("-> existing record :\n");
dump(&buffer[target], length); dump(&buffer[target], length);
printf("-> full MFT record :\n"); printf("-> full MFT record :\n");
skipping to change at line 913 skipping to change at line 914
{ {
LCN lcn; LCN lcn;
ATTR_RECORD *attr; ATTR_RECORD *attr;
int err; int err;
BOOL found; BOOL found;
err = 1; err = 1;
if (action->record.undo_length != action->record.redo_length) if (action->record.undo_length != action->record.redo_length)
printf("** Error size change in change_resident\n"); printf("** Error size change in change_resident\n");
if (optv > 1) { if (optv > 1) {
lcn = le64_to_cpu(action->record.lcn_list[0]); lcn = sle64_to_cpu(action->record.lcn_list[0]);
printf("-> inode %lld lcn 0x%llx target 0x%x length %d\n", printf("-> inode %lld lcn 0x%llx target 0x%x length %d\n",
(long long)inode_number(&action->record), (long long)inode_number(&action->record),
(long long)lcn, (int)target, (int)length); (long long)lcn, (int)target, (int)length);
} }
attr = (ATTR_RECORD*)(buffer attr = (ATTR_RECORD*)(buffer
+ le16_to_cpu(action->record.record_offset)); + le16_to_cpu(action->record.record_offset));
if (optv > 1) { if (optv > 1) {
printf("-> existing record :\n"); printf("-> existing record :\n");
dump(&buffer[target], length); dump(&buffer[target], length);
printf("-> full record :\n"); printf("-> full record :\n");
skipping to change at line 965 skipping to change at line 966
{ {
LCN lcn; LCN lcn;
u32 count; u32 count;
u32 xsize; u32 xsize;
int changed; int changed;
int err; int err;
err = 1; err = 1;
count = le16_to_cpu(action->record.lcns_to_follow); count = le16_to_cpu(action->record.lcns_to_follow);
if (optv > 1) { if (optv > 1) {
lcn = le64_to_cpu(action->record.lcn_list[0]); lcn = sle64_to_cpu(action->record.lcn_list[0]);
printf("-> lcn 0x%llx target 0x%x length %d\n", printf("-> lcn 0x%llx target 0x%x length %d\n",
(long long)lcn, (int)target, (int)length); (long long)lcn, (int)target, (int)length);
} }
xsize = vol->indx_record_size; xsize = vol->indx_record_size;
if (optv > 1) { if (optv > 1) {
printf("-> existing record :\n"); printf("-> existing record :\n");
dump(&buffer[target], length); dump(&buffer[target], length);
} }
if ((target + length) <= (count << clusterbits)) { if ((target + length) <= (count << clusterbits)) {
changed = memcmp(buffer + target, data, length); changed = memcmp(buffer + target, data, length);
skipping to change at line 1010 skipping to change at line 1011
u32 length, u32 oldlength) u32 length, u32 oldlength)
{ {
LCN lcn; LCN lcn;
MFT_RECORD *entry; MFT_RECORD *entry;
int err; int err;
BOOL found; BOOL found;
int resize; int resize;
err = 1; err = 1;
if (optv > 1) { if (optv > 1) {
lcn = le64_to_cpu(action->record.lcn_list[0]); lcn = sle64_to_cpu(action->record.lcn_list[0]);
printf("-> inode %lld lcn 0x%llx target 0x%x length %d\n", printf("-> inode %lld lcn 0x%llx target 0x%x length %d\n",
(long long)inode_number(&action->record), (long long)inode_number(&action->record),
(long long)lcn, (int)target, (int)length); (long long)lcn, (int)target, (int)length);
} }
entry = (MFT_RECORD*)buffer; entry = (MFT_RECORD*)buffer;
resize = length - oldlength; resize = length - oldlength;
if (optv > 1) { if (optv > 1) {
printf("existing data :\n"); printf("existing data :\n");
dump(buffer + target,length); dump(buffer + target,length);
} }
skipping to change at line 1092 skipping to change at line 1093
LCN lcn; LCN lcn;
ATTR_RECORD *attr; ATTR_RECORD *attr;
MFT_RECORD *entry; MFT_RECORD *entry;
int err; int err;
BOOL found; BOOL found;
int resize; int resize;
u16 base; u16 base;
err = 1; err = 1;
if (optv > 1) { if (optv > 1) {
lcn = le64_to_cpu(action->record.lcn_list[0]); lcn = sle64_to_cpu(action->record.lcn_list[0]);
printf("-> inode %lld lcn 0x%llx target 0x%x length %d\n", printf("-> inode %lld lcn 0x%llx target 0x%x length %d\n",
(long long)inode_number(&action->record), (long long)inode_number(&action->record),
(long long)lcn, (int)target, (int)length); (long long)lcn, (int)target, (int)length);
} }
entry = (MFT_RECORD*)buffer; entry = (MFT_RECORD*)buffer;
attr = (ATTR_RECORD*)(buffer attr = (ATTR_RECORD*)(buffer
+ le16_to_cpu(action->record.record_offset)); + le16_to_cpu(action->record.record_offset));
if (optv > 1) { if (optv > 1) {
printf("existing data :\n"); printf("existing data :\n");
dump(buffer + target,length); dump(buffer + target,length);
skipping to change at line 1175 skipping to change at line 1176
ATTR_RECORD *attr; ATTR_RECORD *attr;
const ATTR_RECORD *newattr; const ATTR_RECORD *newattr;
MFT_RECORD *entry; MFT_RECORD *entry;
u32 newused; u32 newused;
u16 links; u16 links;
int err; int err;
BOOL found; BOOL found;
err = 1; err = 1;
if (optv > 1) { if (optv > 1) {
lcn = le64_to_cpu(action->record.lcn_list[0]); lcn = sle64_to_cpu(action->record.lcn_list[0]);
printf("-> inode %lld lcn 0x%llx target 0x%x length %d\n", printf("-> inode %lld lcn 0x%llx target 0x%x length %d\n",
(long long)inode_number(&action->record), (long long)inode_number(&action->record),
(long long)lcn, (int)target, (int)length); (long long)lcn, (int)target, (int)length);
} }
entry = (MFT_RECORD*)buffer; entry = (MFT_RECORD*)buffer;
attr = (ATTR_RECORD*)(buffer attr = (ATTR_RECORD*)(buffer
+ le16_to_cpu(action->record.record_offset)); + le16_to_cpu(action->record.record_offset));
newattr = (const ATTR_RECORD*)data; newattr = (const ATTR_RECORD*)data;
if (optv > 1) { if (optv > 1) {
printf("existing record :\n"); printf("existing record :\n");
skipping to change at line 1257 skipping to change at line 1258
LCN lcn; LCN lcn;
ATTR_RECORD *attr; ATTR_RECORD *attr;
MFT_RECORD *entry; MFT_RECORD *entry;
u32 newused; u32 newused;
u16 links; u16 links;
int err; int err;
BOOL found; BOOL found;
err = 1; err = 1;
if (optv > 1) { if (optv > 1) {
lcn = le64_to_cpu(action->record.lcn_list[0]); lcn = sle64_to_cpu(action->record.lcn_list[0]);
printf("-> inode %lld lcn 0x%llx target 0x%x length %d\n", printf("-> inode %lld lcn 0x%llx target 0x%x length %d\n",
(long long)inode_number(&action->record), (long long)inode_number(&action->record),
(long long)lcn, (int)target, (int)length); (long long)lcn, (int)target, (int)length);
} }
entry = (MFT_RECORD*)buffer; entry = (MFT_RECORD*)buffer;
attr = (ATTR_RECORD*)(buffer attr = (ATTR_RECORD*)(buffer
+ le16_to_cpu(action->record.record_offset)); + le16_to_cpu(action->record.record_offset));
if (optv > 1) { if (optv > 1) {
printf("existing record :\n"); printf("existing record :\n");
dump(buffer + target,length); dump(buffer + target,length);
skipping to change at line 1343 skipping to change at line 1344
LCN lcn; LCN lcn;
MFT_RECORD *entry; MFT_RECORD *entry;
int err; int err;
BOOL found; BOOL found;
int resize; int resize;
if (optv > 1) if (optv > 1)
printf("-> %s()\n",__func__); printf("-> %s()\n",__func__);
err = 1; err = 1;
if (optv > 1) { if (optv > 1) {
lcn = le64_to_cpu(action->record.lcn_list[0]); lcn = sle64_to_cpu(action->record.lcn_list[0]);
printf("-> inode %lld lcn 0x%llx target 0x%x length %d\n", printf("-> inode %lld lcn 0x%llx target 0x%x length %d\n",
(long long)inode_number(&action->record), (long long)inode_number(&action->record),
(long long)lcn, (int)target, (int)length); (long long)lcn, (int)target, (int)length);
} }
entry = (MFT_RECORD*)buffer; entry = (MFT_RECORD*)buffer;
if (optv > 1) { if (optv > 1) {
printf("existing data :\n"); printf("existing data :\n");
dump(buffer + target,length); dump(buffer + target,length);
} }
resize = length - oldlength; resize = length - oldlength;
skipping to change at line 1403 skipping to change at line 1404
MFT_RECORD *entry; MFT_RECORD *entry;
int err; int err;
BOOL found; BOOL found;
int resize; int resize;
u16 base; u16 base;
if (optv > 1) if (optv > 1)
printf("-> %s()\n",__func__); printf("-> %s()\n",__func__);
err = 1; err = 1;
if (optv > 1) { if (optv > 1) {
lcn = le64_to_cpu(action->record.lcn_list[0]); lcn = sle64_to_cpu(action->record.lcn_list[0]);
printf("-> inode %lld lcn 0x%llx target 0x%x length %d\n", printf("-> inode %lld lcn 0x%llx target 0x%x length %d\n",
(long long)inode_number(&action->record), (long long)inode_number(&action->record),
(long long)lcn, (int)target, (int)length); (long long)lcn, (int)target, (int)length);
} }
entry = (MFT_RECORD*)buffer; entry = (MFT_RECORD*)buffer;
attr = (ATTR_RECORD*)(buffer attr = (ATTR_RECORD*)(buffer
+ le16_to_cpu(action->record.record_offset)); + le16_to_cpu(action->record.record_offset));
if (optv > 1) { if (optv > 1) {
printf("existing data :\n"); printf("existing data :\n");
dump(buffer + target,length); dump(buffer + target,length);
skipping to change at line 1479 skipping to change at line 1480
char *buffer, const char *data, u32 target, u32 length) char *buffer, const char *data, u32 target, u32 length)
{ {
LCN lcn; LCN lcn;
INDEX_BLOCK *indx; INDEX_BLOCK *indx;
u32 xsize; u32 xsize;
BOOL changed; BOOL changed;
int err; int err;
err = 1; err = 1;
if (optv > 1) { if (optv > 1) {
lcn = le64_to_cpu(action->record.lcn_list[0]); lcn = sle64_to_cpu(action->record.lcn_list[0]);
printf("-> lcn 0x%llx target 0x%x length %d\n", printf("-> lcn 0x%llx target 0x%x length %d\n",
(long long)lcn, (int)target, (int)length); (long long)lcn, (int)target, (int)length);
} }
xsize = vol->indx_record_size; xsize = vol->indx_record_size;
indx = (INDEX_BLOCK*)(buffer indx = (INDEX_BLOCK*)(buffer
+ le16_to_cpu(action->record.record_offset)); + le16_to_cpu(action->record.record_offset));
if (optv > 1) { if (optv > 1) {
printf("-> existing index :\n"); printf("-> existing index :\n");
dump(&buffer[target], length); dump(&buffer[target], length);
} }
skipping to change at line 1787 skipping to change at line 1788
printf("** Call to unsupported create_indx()\n"); printf("** Call to unsupported create_indx()\n");
err = 1; err = 1;
} else { } else {
err = 0; err = 0;
indx = (INDEX_BLOCK*)buffer; indx = (INDEX_BLOCK*)buffer;
indx->magic = magic_INDX; indx->magic = magic_INDX;
// TODO compute properly // TODO compute properly
indx->usa_ofs = const_cpu_to_le16(0x28); indx->usa_ofs = const_cpu_to_le16(0x28);
indx->usa_count = const_cpu_to_le16(9); indx->usa_count = const_cpu_to_le16(9);
indx->lsn = action->record.this_lsn; indx->lsn = action->record.this_lsn;
vcn = le32_to_cpu(action->record.target_vcn); vcn = sle64_to_cpu(action->record.target_vcn);
/* beware of size change on big-endian cpus */ /* beware of size change on big-endian cpus */
indx->index_block_vcn = cpu_to_sle64(vcn); indx->index_block_vcn = cpu_to_sle64(vcn);
/* INDEX_HEADER */ /* INDEX_HEADER */
indx->index.entries_offset = const_cpu_to_le32(0x28); indx->index.entries_offset = const_cpu_to_le32(0x28);
indx->index.index_length = const_cpu_to_le32(0x38); indx->index.index_length = const_cpu_to_le32(0x38);
indx->index.allocated_size = indx->index.allocated_size =
cpu_to_le32(vol->indx_record_size - 24); cpu_to_le32(vol->indx_record_size - 24);
indx->index.ih_flags = 0; indx->index.ih_flags = 0;
/* INDEX_ENTRY_HEADER */ /* INDEX_ENTRY_HEADER */
ixhead = (INDEX_ENTRY_HEADER*)(buffer + 0x28); ixhead = (INDEX_ENTRY_HEADER*)(buffer + 0x28);
skipping to change at line 1866 skipping to change at line 1867
if (optv > 1) if (optv > 1)
printf("-> %s()\n",__func__); printf("-> %s()\n",__func__);
err = 1; err = 1;
data = ((const char*)&action->record) data = ((const char*)&action->record)
+ get_redo_offset(&action->record); + get_redo_offset(&action->record);
length = le16_to_cpu(action->record.redo_length); length = le16_to_cpu(action->record.redo_length);
target = le16_to_cpu(action->record.record_offset) target = le16_to_cpu(action->record.record_offset)
+ le16_to_cpu(action->record.attribute_offset); + le16_to_cpu(action->record.attribute_offset);
if (optv > 1) { if (optv > 1) {
lcn = le64_to_cpu(action->record.lcn_list[0]); lcn = sle64_to_cpu(action->record.lcn_list[0]);
printf("-> lcn 0x%llx target 0x%x length %d\n", printf("-> lcn 0x%llx target 0x%x length %d\n",
(long long)lcn, (int)target, (int)length); (long long)lcn, (int)target, (int)length);
} }
xsize = vol->indx_record_size; xsize = vol->indx_record_size;
indx = (INDEX_BLOCK*)(buffer indx = (INDEX_BLOCK*)(buffer
+ le16_to_cpu(action->record.record_offset)); + le16_to_cpu(action->record.record_offset));
if (optv > 1) { if (optv > 1) {
printf("-> existing record :\n"); printf("-> existing record :\n");
dump(&buffer[target], length); dump(&buffer[target], length);
} }
skipping to change at line 1929 skipping to change at line 1930
if (optv > 1) if (optv > 1)
printf("-> %s()\n",__func__); printf("-> %s()\n",__func__);
err = 1; err = 1;
data = ((const char*)&action->record) data = ((const char*)&action->record)
+ get_redo_offset(&action->record); + get_redo_offset(&action->record);
length = le16_to_cpu(action->record.redo_length); length = le16_to_cpu(action->record.redo_length);
target = le16_to_cpu(action->record.record_offset) target = le16_to_cpu(action->record.record_offset)
+ le16_to_cpu(action->record.attribute_offset); + le16_to_cpu(action->record.attribute_offset);
if (optv > 1) { if (optv > 1) {
lcn = le64_to_cpu(action->record.lcn_list[0]); lcn = sle64_to_cpu(action->record.lcn_list[0]);
printf("-> inode %lld lcn 0x%llx target 0x%x length %d\n", printf("-> inode %lld lcn 0x%llx target 0x%x length %d\n",
(long long)inode_number(&action->record), (long long)inode_number(&action->record),
(long long)lcn, (int)target, (int)length); (long long)lcn, (int)target, (int)length);
} }
entry = (MFT_RECORD*)buffer; entry = (MFT_RECORD*)buffer;
attr = (ATTR_RECORD*)(buffer attr = (ATTR_RECORD*)(buffer
+ le16_to_cpu(action->record.record_offset)); + le16_to_cpu(action->record.record_offset));
index = (INDEX_ROOT*)(((char*)attr) index = (INDEX_ROOT*)(((char*)attr)
+ le16_to_cpu(attr->value_offset)); + le16_to_cpu(attr->value_offset));
if (optv > 1) { if (optv > 1) {
skipping to change at line 2007 skipping to change at line 2008
if (optv > 1) if (optv > 1)
printf("-> %s()\n",__func__); printf("-> %s()\n",__func__);
err = 1; err = 1;
data = ((const char*)&action->record) data = ((const char*)&action->record)
+ get_redo_offset(&action->record); + get_redo_offset(&action->record);
length = le16_to_cpu(action->record.redo_length); length = le16_to_cpu(action->record.redo_length);
target = le16_to_cpu(action->record.record_offset) target = le16_to_cpu(action->record.record_offset)
+ le16_to_cpu(action->record.attribute_offset); + le16_to_cpu(action->record.attribute_offset);
if (optv > 1) { if (optv > 1) {
lcn = le64_to_cpu(action->record.lcn_list[0]); lcn = sle64_to_cpu(action->record.lcn_list[0]);
printf("-> inode %lld lcn 0x%llx target 0x%x length %d\n", printf("-> inode %lld lcn 0x%llx target 0x%x length %d\n",
(long long)inode_number(&action->record), (long long)inode_number(&action->record),
(long long)lcn, (int)target, (int)length); (long long)lcn, (int)target, (int)length);
} }
record = (MFT_RECORD*)buffer; record = (MFT_RECORD*)buffer;
if (optv > 1) { if (optv > 1) {
printf("-> existing record :\n"); printf("-> existing record :\n");
dump(buffer,mftrecsz); dump(buffer,mftrecsz);
} }
if ((target + length) <= mftrecsz) { if ((target + length) <= mftrecsz) {
skipping to change at line 2105 skipping to change at line 2106
if (optv > 1) if (optv > 1)
printf("-> %s()\n",__func__); printf("-> %s()\n",__func__);
err = 1; err = 1;
data = ((const char*)&action->record) data = ((const char*)&action->record)
+ get_undo_offset(&action->record); + get_undo_offset(&action->record);
length = le16_to_cpu(action->record.undo_length); length = le16_to_cpu(action->record.undo_length);
target = le16_to_cpu(action->record.record_offset) target = le16_to_cpu(action->record.record_offset)
+ le16_to_cpu(action->record.attribute_offset); + le16_to_cpu(action->record.attribute_offset);
if (optv > 1) { if (optv > 1) {
lcn = le64_to_cpu(action->record.lcn_list[0]); lcn = sle64_to_cpu(action->record.lcn_list[0]);
printf("-> inode %lld lcn 0x%llx target 0x%x length %d\n", printf("-> inode %lld lcn 0x%llx target 0x%x length %d\n",
(long long)inode_number(&action->record), (long long)inode_number(&action->record),
(long long)lcn, (int)target, (int)length); (long long)lcn, (int)target, (int)length);
} }
if (optv > 1) { if (optv > 1) {
printf("-> existing record :\n"); printf("-> existing record :\n");
dump(buffer,mftrecsz); dump(buffer,mftrecsz);
} }
record = (MFT_RECORD*)buffer; record = (MFT_RECORD*)buffer;
if ((target + length) <= mftrecsz) { if ((target + length) <= mftrecsz) {
skipping to change at line 2161 skipping to change at line 2162
if (optv > 1) if (optv > 1)
printf("-> %s()\n",__func__); printf("-> %s()\n",__func__);
err = 1; err = 1;
data = ((const char*)&action->record) data = ((const char*)&action->record)
+ get_undo_offset(&action->record); + get_undo_offset(&action->record);
length = le16_to_cpu(action->record.undo_length); length = le16_to_cpu(action->record.undo_length);
// TODO merge with undo_add_index ? // TODO merge with undo_add_index ?
target = le16_to_cpu(action->record.record_offset) target = le16_to_cpu(action->record.record_offset)
+ le16_to_cpu(action->record.attribute_offset); + le16_to_cpu(action->record.attribute_offset);
if (optv > 1) { if (optv > 1) {
lcn = le64_to_cpu(action->record.lcn_list[0]); lcn = sle64_to_cpu(action->record.lcn_list[0]);
printf("-> lcn 0x%llx target 0x%x length %d\n", printf("-> lcn 0x%llx target 0x%x length %d\n",
(long long)lcn, (int)target, (int)length); (long long)lcn, (int)target, (int)length);
} }
xsize = vol->indx_record_size; xsize = vol->indx_record_size;
indx = (INDEX_BLOCK*)(buffer indx = (INDEX_BLOCK*)(buffer
+ le16_to_cpu(action->record.record_offset)); + le16_to_cpu(action->record.record_offset));
if (optv > 1) { if (optv > 1) {
printf("-> existing record :\n"); printf("-> existing record :\n");
dump(&buffer[target], length); dump(&buffer[target], length);
} }
skipping to change at line 2220 skipping to change at line 2221
if (optv > 1) if (optv > 1)
printf("-> %s()\n",__func__); printf("-> %s()\n",__func__);
err = 1; err = 1;
data = ((const char*)&action->record) data = ((const char*)&action->record)
+ get_undo_offset(&action->record); + get_undo_offset(&action->record);
length = le16_to_cpu(action->record.undo_length); length = le16_to_cpu(action->record.undo_length);
target = le16_to_cpu(action->record.record_offset) target = le16_to_cpu(action->record.record_offset)
+ le16_to_cpu(action->record.attribute_offset); + le16_to_cpu(action->record.attribute_offset);
if (optv > 1) { if (optv > 1) {
lcn = le64_to_cpu(action->record.lcn_list[0]); lcn = sle64_to_cpu(action->record.lcn_list[0]);
printf("-> inode %lld lcn 0x%llx target 0x%x length %d\n", printf("-> inode %lld lcn 0x%llx target 0x%x length %d\n",
(long long)inode_number(&action->record), (long long)inode_number(&action->record),
(long long)lcn, (int)target, (int)length); (long long)lcn, (int)target, (int)length);
} }
entry = (MFT_RECORD*)buffer; entry = (MFT_RECORD*)buffer;
attr = (ATTR_RECORD*)(buffer attr = (ATTR_RECORD*)(buffer
+ le16_to_cpu(action->record.record_offset)); + le16_to_cpu(action->record.record_offset));
index = (INDEX_ROOT*)(((char*)attr) index = (INDEX_ROOT*)(((char*)attr)
+ le16_to_cpu(attr->value_offset)); + le16_to_cpu(attr->value_offset));
if (optv > 1) { if (optv > 1) {
skipping to change at line 2289 skipping to change at line 2290
firstbit = le32_to_cpu(data->firstbit); firstbit = le32_to_cpu(data->firstbit);
count = le32_to_cpu(data->count); count = le32_to_cpu(data->count);
if (action->record.redo_operation if (action->record.redo_operation
== const_cpu_to_le16(SetBitsInNonResidentBitMap)) == const_cpu_to_le16(SetBitsInNonResidentBitMap))
wanted = 1; wanted = 1;
else else
wanted = 0; wanted = 0;
// TODO consistency undo_offset == redo_offset, etc. // TODO consistency undo_offset == redo_offset, etc.
// firstbit + count < 8*clustersz (multiple clusters possible ?) // firstbit + count < 8*clustersz (multiple clusters possible ?)
if (optv > 1) { if (optv > 1) {
lcn = le64_to_cpu(action->record.lcn_list[0]); lcn = sle64_to_cpu(action->record.lcn_list[0]);
printf("-> lcn 0x%llx firstbit %d count %d wanted %d\n", printf("-> lcn 0x%llx firstbit %d count %d wanted %d\n",
(long long)lcn,(int)firstbit,(int)count,(int)wanted); (long long)lcn,(int)firstbit,(int)count,(int)wanted);
} }
for (i=0; i<count; i++) for (i=0; i<count; i++)
ntfs_bit_set((u8*)buffer, firstbit + i, wanted); ntfs_bit_set((u8*)buffer, firstbit + i, wanted);
if (!write_raw(vol, &action->record, buffer)) { if (!write_raw(vol, &action->record, buffer)) {
err = 0; err = 0;
if (optv > 1) if (optv > 1)
printf("-> record updated\n"); printf("-> record updated\n");
} }
if (err) if (err)
printf("** redo_clearbits failed\n"); printf("** redo_clearbits failed\n");
return (err); return (err);
} }
static int redo_open_attribute(ntfs_volume *vol __attribute__((unused)), static int redo_open_attribute(ntfs_volume *vol __attribute__((unused)),
const struct ACTION_RECORD *action) const struct ACTION_RECORD *action)
{ {
const char *data; const char *data;
struct ATTR *pa; struct ATTR *pa;
const struct ATTR_OLD *attr_old; const ATTR_OLD *attr_old;
const struct ATTR_NEW *attr_new; const ATTR_NEW *attr_new;
const char *name; const char *name;
le64 inode; le64 inode;
u32 namelen; u32 namelen;
u32 length; u32 length;
u32 extra; u32 extra;
int err; int err;
if (optv > 1) if (optv > 1)
printf("-> %s()\n",__func__); printf("-> %s()\n",__func__);
err = 1; err = 1;
skipping to change at line 2350 skipping to change at line 2351
} }
pa = getattrentry(le16_to_cpu(action->record.target_attribute),0); pa = getattrentry(le16_to_cpu(action->record.target_attribute),0);
if (pa) { if (pa) {
if (optv) { if (optv) {
/* /*
* If the actions have been displayed, the * If the actions have been displayed, the
* attribute has already been fed. Check * attribute has already been fed. Check
* whether it matches what we have in store. * whether it matches what we have in store.
*/ */
switch (length) { switch (length) {
case sizeof(struct ATTR_OLD) : case sizeof(ATTR_OLD) :
attr_old = (const struct ATTR_OLD*)data; attr_old = (const ATTR_OLD*)data;
/* Badly aligned */ /* Badly aligned */
memcpy(&inode, &attr_old->inode, 8); memcpy(&inode, &attr_old->inode, 8);
err = (MREF(le64_to_cpu(inode)) != pa->inode) err = (MREF(le64_to_cpu(inode)) != pa->inode)
|| (attr_old->type != pa->type); || (attr_old->type != pa->type);
break; break;
case sizeof(struct ATTR_NEW) : case sizeof(ATTR_NEW) :
attr_new = (const struct ATTR_NEW*)data; attr_new = (const ATTR_NEW*)data;
err = (MREF(le64_to_cpu(attr_new->inode)) err = (MREF(le64_to_cpu(attr_new->inode))
!= pa->inode) != pa->inode)
|| (attr_new->type != pa->type); || (attr_new->type != pa->type);
break; break;
default : err = 1; default : err = 1;
} }
if (!err) { if (!err) {
err = (namelen != pa->namelen) err = (namelen != pa->namelen)
|| (namelen || (namelen
&& memcmp(name, pa->name, namelen)); && memcmp(name, pa->name, namelen));
skipping to change at line 2476 skipping to change at line 2477
if (optv > 1) if (optv > 1)
printf("-> %s()\n",__func__); printf("-> %s()\n",__func__);
err = 1; err = 1;
data = ((const char*)&action->record) data = ((const char*)&action->record)
+ get_redo_offset(&action->record); + get_redo_offset(&action->record);
length = le16_to_cpu(action->record.redo_length); length = le16_to_cpu(action->record.redo_length);
resize = length - le16_to_cpu(action->record.undo_length); resize = length - le16_to_cpu(action->record.undo_length);
target = le16_to_cpu(action->record.record_offset) target = le16_to_cpu(action->record.record_offset)
+ le16_to_cpu(action->record.attribute_offset); + le16_to_cpu(action->record.attribute_offset);
if (optv > 1) { if (optv > 1) {
lcn = le64_to_cpu(action->record.lcn_list[0]); lcn = sle64_to_cpu(action->record.lcn_list[0]);
printf("-> inode %lld lcn 0x%llx target 0x%x length %d\n", printf("-> inode %lld lcn 0x%llx target 0x%x length %d\n",
(long long)inode_number(&action->record), (long long)inode_number(&action->record),
(long long)lcn, (int)target, (int)length); (long long)lcn, (int)target, (int)length);
} }
if (optv > 1) { if (optv > 1) {
printf("-> existing record :\n"); printf("-> existing record :\n");
dump(&buffer[target], length); dump(&buffer[target], length);
} }
entry = (MFT_RECORD*)buffer; entry = (MFT_RECORD*)buffer;
attr = (ATTR_RECORD*)(buffer attr = (ATTR_RECORD*)(buffer
skipping to change at line 2567 skipping to change at line 2568
redo = get_redo_offset(&action->record); redo = get_redo_offset(&action->record);
if ((redo + length) > end) if ((redo + length) > end)
data = (char*)NULL; data = (char*)NULL;
else else
data = ((const char*)&action->record) + redo; data = ((const char*)&action->record) + redo;
oldlength = le16_to_cpu(action->record.undo_length); oldlength = le16_to_cpu(action->record.undo_length);
target = le16_to_cpu(action->record.record_offset) target = le16_to_cpu(action->record.record_offset)
+ le16_to_cpu(action->record.attribute_offset); + le16_to_cpu(action->record.attribute_offset);
if (length == oldlength) { if (length == oldlength) {
if (optv > 1) { if (optv > 1) {
lcn = le64_to_cpu(action->record.lcn_list[0]); lcn = sle64_to_cpu(action->record.lcn_list[0]);
printf("-> inode %lld lcn 0x%llx target 0x%x" printf("-> inode %lld lcn 0x%llx target 0x%x"
" length %d\n", " length %d\n",
(long long)inode_number(&action->record), (long long)inode_number(&action->record),
(long long)lcn, (int)target, (int)length); (long long)lcn, (int)target, (int)length);
} }
if (optv > 1) { if (optv > 1) {
printf("-> existing record :\n"); printf("-> existing record :\n");
dump(&buffer[target], length); dump(&buffer[target], length);
} }
if ((target + length) <= mftrecsz) { if ((target + length) <= mftrecsz) {
skipping to change at line 2688 skipping to change at line 2689
+ LOG_RECORD_HEAD_SZ; + LOG_RECORD_HEAD_SZ;
/* sometimes there is no redo data */ /* sometimes there is no redo data */
if ((redo + length) > end) if ((redo + length) > end)
data = (char*)NULL; data = (char*)NULL;
else else
data = ((const char*)&action->record) + redo; data = ((const char*)&action->record) + redo;
target = le16_to_cpu(action->record.record_offset) target = le16_to_cpu(action->record.record_offset)
+ le16_to_cpu(action->record.attribute_offset); + le16_to_cpu(action->record.attribute_offset);
count = le16_to_cpu(action->record.lcns_to_follow); count = le16_to_cpu(action->record.lcns_to_follow);
if (optv > 1) { if (optv > 1) {
lcn = le64_to_cpu(action->record.lcn_list[0]); lcn = sle64_to_cpu(action->record.lcn_list[0]);
printf("-> lcn 0x%llx target 0x%x length %d\n", printf("-> lcn 0x%llx target 0x%x length %d\n",
(long long)lcn, (int)target, (int)length); (long long)lcn, (int)target, (int)length);
} }
if (optv > 1) { if (optv > 1) {
printf("-> existing record :\n"); printf("-> existing record :\n");
dump(&buffer[target], length); dump(&buffer[target], length);
} }
if ((target + length) <= (count << clusterbits)) { if ((target + length) <= (count << clusterbits)) {
if (data) if (data)
changed = memcmp(buffer + target, data, length); changed = memcmp(buffer + target, data, length);
skipping to change at line 2775 skipping to change at line 2776
redo = get_redo_offset(&action->record); redo = get_redo_offset(&action->record);
if ((redo + length) > end) if ((redo + length) > end)
data = (char*)NULL; data = (char*)NULL;
else else
data = ((const char*)&action->record) + redo; data = ((const char*)&action->record) + redo;
oldlength = le16_to_cpu(action->record.undo_length); oldlength = le16_to_cpu(action->record.undo_length);
target = le16_to_cpu(action->record.record_offset) target = le16_to_cpu(action->record.record_offset)
+ le16_to_cpu(action->record.attribute_offset); + le16_to_cpu(action->record.attribute_offset);
if (length == oldlength) { if (length == oldlength) {
if (optv > 1) { if (optv > 1) {
lcn = le64_to_cpu(action->record.lcn_list[0]); lcn = sle64_to_cpu(action->record.lcn_list[0]);
printf("-> inode %lld lcn 0x%llx target 0x%x" printf("-> inode %lld lcn 0x%llx target 0x%x"
" length %d\n", " length %d\n",
(long long)inode_number(&action->record), (long long)inode_number(&action->record),
(long long)lcn, (int)target, (int)length); (long long)lcn, (int)target, (int)length);
} }
if (optv > 1) { if (optv > 1) {
printf("-> existing record :\n"); printf("-> existing record :\n");
dump(&buffer[target], length); dump(&buffer[target], length);
} }
if ((target + length) <= mftrecsz) { if ((target + length) <= mftrecsz) {
skipping to change at line 2835 skipping to change at line 2836
if (optv > 1) if (optv > 1)
printf("-> %s()\n",__func__); printf("-> %s()\n",__func__);
err = 1; err = 1;
data = ((const char*)&action->record) data = ((const char*)&action->record)
+ get_redo_offset(&action->record); + get_redo_offset(&action->record);
length = le16_to_cpu(action->record.redo_length); length = le16_to_cpu(action->record.redo_length);
/* target is left-justified to creation time */ /* target is left-justified to creation time */
target = le16_to_cpu(action->record.record_offset) target = le16_to_cpu(action->record.record_offset)
+ le16_to_cpu(action->record.attribute_offset); + le16_to_cpu(action->record.attribute_offset);
if (optv > 1) { if (optv > 1) {
lcn = le64_to_cpu(action->record.lcn_list[0]); lcn = sle64_to_cpu(action->record.lcn_list[0]);
printf("-> lcn 0x%llx target 0x%x length %d\n", printf("-> lcn 0x%llx target 0x%x length %d\n",
(long long)lcn, (int)target, (int)length); (long long)lcn, (int)target, (int)length);
} }
xsize = vol->indx_record_size; xsize = vol->indx_record_size;
indx = (INDEX_BLOCK*)buffer; indx = (INDEX_BLOCK*)buffer;
if (action->record.record_offset) { if (action->record.record_offset) {
printf("** Non-null record_offset in redo_write_index()\n"); printf("** Non-null record_offset in redo_write_index()\n");
} }
if (optv > 1) { if (optv > 1) {
printf("-> existing index :\n"); printf("-> existing index :\n");
skipping to change at line 2924 skipping to change at line 2925
if (optv > 1) if (optv > 1)
printf("-> %s()\n",__func__); printf("-> %s()\n",__func__);
err = 1; err = 1;
data = ((const char*)&action->record) data = ((const char*)&action->record)
+ get_redo_offset(&action->record); + get_redo_offset(&action->record);
length = le16_to_cpu(action->record.redo_length); length = le16_to_cpu(action->record.redo_length);
target = le16_to_cpu(action->record.record_offset) target = le16_to_cpu(action->record.record_offset)
+ le16_to_cpu(action->record.attribute_offset); + le16_to_cpu(action->record.attribute_offset);
if (optv > 1) { if (optv > 1) {
lcn = le64_to_cpu(action->record.lcn_list[0]); lcn = sle64_to_cpu(action->record.lcn_list[0]);
printf("-> lcn 0x%llx target 0x%x length %d\n", printf("-> lcn 0x%llx target 0x%x length %d\n",
(long long)lcn, (int)target, (int)length); (long long)lcn, (int)target, (int)length);
} }
xsize = vol->indx_record_size; xsize = vol->indx_record_size;
indx = (INDEX_BLOCK*)(buffer indx = (INDEX_BLOCK*)(buffer
+ le16_to_cpu(action->record.record_offset)); + le16_to_cpu(action->record.record_offset));
if (optv > 1) { if (optv > 1) {
printf("-> existing record :\n"); printf("-> existing record :\n");
dump(&buffer[target], length); dump(&buffer[target], length);
} }
skipping to change at line 2986 skipping to change at line 2987
if (optv > 1) if (optv > 1)
printf("-> %s()\n",__func__); printf("-> %s()\n",__func__);
err = 1; err = 1;
data = ((const char*)&action->record) data = ((const char*)&action->record)
+ get_redo_offset(&action->record); + get_redo_offset(&action->record);
length = le16_to_cpu(action->record.redo_length); length = le16_to_cpu(action->record.redo_length);
target = le16_to_cpu(action->record.record_offset) target = le16_to_cpu(action->record.record_offset)
+ le16_to_cpu(action->record.attribute_offset); + le16_to_cpu(action->record.attribute_offset);
if (optv > 1) { if (optv > 1) {
lcn = le64_to_cpu(action->record.lcn_list[0]); lcn = sle64_to_cpu(action->record.lcn_list[0]);
printf("-> inode %lld lcn 0x%llx target 0x%x length %d\n", printf("-> inode %lld lcn 0x%llx target 0x%x length %d\n",
(long long)inode_number(&action->record), (long long)inode_number(&action->record),
(long long)lcn, (int)target, (int)length); (long long)lcn, (int)target, (int)length);
} }
entry = (MFT_RECORD*)buffer; entry = (MFT_RECORD*)buffer;
attr = (ATTR_RECORD*)(buffer attr = (ATTR_RECORD*)(buffer
+ le16_to_cpu(action->record.record_offset)); + le16_to_cpu(action->record.record_offset));
index = (INDEX_ROOT*)(((char*)attr) index = (INDEX_ROOT*)(((char*)attr)
+ le16_to_cpu(attr->value_offset)); + le16_to_cpu(attr->value_offset));
if (optv > 1) { if (optv > 1) {
skipping to change at line 3094 skipping to change at line 3095
// MERGE with redo_add_root_index() ? // MERGE with redo_add_root_index() ?
if (optv > 1) if (optv > 1)
printf("-> %s()\n",__func__); printf("-> %s()\n",__func__);
err = 1; err = 1;
data = ((const char*)&action->record) data = ((const char*)&action->record)
+ get_undo_offset(&action->record); + get_undo_offset(&action->record);
length = le16_to_cpu(action->record.undo_length); length = le16_to_cpu(action->record.undo_length);
target = le16_to_cpu(action->record.record_offset) target = le16_to_cpu(action->record.record_offset)
+ le16_to_cpu(action->record.attribute_offset); + le16_to_cpu(action->record.attribute_offset);
if (optv > 1) { if (optv > 1) {
lcn = le64_to_cpu(action->record.lcn_list[0]); lcn = sle64_to_cpu(action->record.lcn_list[0]);
printf("-> lcn 0x%llx target 0x%x length %d\n", printf("-> lcn 0x%llx target 0x%x length %d\n",
(long long)lcn, (int)target, (int)length); (long long)lcn, (int)target, (int)length);
} }
xsize = vol->indx_record_size; xsize = vol->indx_record_size;
indx = (INDEX_BLOCK*)(buffer indx = (INDEX_BLOCK*)(buffer
+ le16_to_cpu(action->record.record_offset)); + le16_to_cpu(action->record.record_offset));
if (optv > 1) { if (optv > 1) {
printf("-> existing record :\n"); printf("-> existing record :\n");
dump(&buffer[target], length); dump(&buffer[target], length);
} }
skipping to change at line 3160 skipping to change at line 3161
if (optv > 1) if (optv > 1)
printf("-> %s()\n",__func__); printf("-> %s()\n",__func__);
err = 1; err = 1;
data = ((const char*)&action->record) data = ((const char*)&action->record)
+ get_undo_offset(&action->record); + get_undo_offset(&action->record);
length = le16_to_cpu(action->record.undo_length); length = le16_to_cpu(action->record.undo_length);
target = le16_to_cpu(action->record.record_offset) target = le16_to_cpu(action->record.record_offset)
+ le16_to_cpu(action->record.attribute_offset); + le16_to_cpu(action->record.attribute_offset);
if (optv > 1) { if (optv > 1) {
lcn = le64_to_cpu(action->record.lcn_list[0]); lcn = sle64_to_cpu(action->record.lcn_list[0]);
printf("-> inode %lld lcn 0x%llx target 0x%x length %d\n", printf("-> inode %lld lcn 0x%llx target 0x%x length %d\n",
(long long)inode_number(&action->record), (long long)inode_number(&action->record),
(long long)lcn, (int)target, (int)length); (long long)lcn, (int)target, (int)length);
} }
entry = (MFT_RECORD*)buffer; entry = (MFT_RECORD*)buffer;
attr = (ATTR_RECORD*)(buffer attr = (ATTR_RECORD*)(buffer
+ le16_to_cpu(action->record.record_offset)); + le16_to_cpu(action->record.record_offset));
index = (INDEX_ROOT*)(((char*)attr) index = (INDEX_ROOT*)(((char*)attr)
+ le16_to_cpu(attr->value_offset)); + le16_to_cpu(attr->value_offset));
if (attr->type != AT_INDEX_ROOT) { if (attr->type != AT_INDEX_ROOT) {
skipping to change at line 3232 skipping to change at line 3233
if (optv > 1) if (optv > 1)
printf("-> %s()\n",__func__); printf("-> %s()\n",__func__);
err = 1; err = 1;
/* redo initialize, clearing the in_use flag ? */ /* redo initialize, clearing the in_use flag ? */
data = ((const char*)&action->record) data = ((const char*)&action->record)
+ get_redo_offset(&action->record); + get_redo_offset(&action->record);
length = le16_to_cpu(action->record.redo_length); length = le16_to_cpu(action->record.redo_length);
target = le16_to_cpu(action->record.record_offset) target = le16_to_cpu(action->record.record_offset)
+ le16_to_cpu(action->record.attribute_offset); + le16_to_cpu(action->record.attribute_offset);
if (optv > 1) { if (optv > 1) {
lcn = le64_to_cpu(action->record.lcn_list[0]); lcn = sle64_to_cpu(action->record.lcn_list[0]);
printf("-> inode %lld lcn 0x%llx target 0x%x length %d\n", printf("-> inode %lld lcn 0x%llx target 0x%x length %d\n",
(long long)inode_number(&action->record), (long long)inode_number(&action->record),
(long long)lcn, (int)target, (int)length); (long long)lcn, (int)target, (int)length);
} }
record = (MFT_RECORD*)buffer; record = (MFT_RECORD*)buffer;
if (optv > 1) { if (optv > 1) {
printf("-> existing record :\n"); printf("-> existing record :\n");
dump(buffer,mftrecsz); dump(buffer,mftrecsz);
} }
if ((target + length) <= mftrecsz) { if ((target + length) <= mftrecsz) {
skipping to change at line 3283 skipping to change at line 3284
if (optv > 1) if (optv > 1)
printf("-> %s()\n",__func__); printf("-> %s()\n",__func__);
err = 1; err = 1;
data = ((const char*)&action->record) data = ((const char*)&action->record)
+ get_undo_offset(&action->record); + get_undo_offset(&action->record);
length = le16_to_cpu(action->record.undo_length); length = le16_to_cpu(action->record.undo_length);
target = le16_to_cpu(action->record.record_offset) target = le16_to_cpu(action->record.record_offset)
+ le16_to_cpu(action->record.attribute_offset); + le16_to_cpu(action->record.attribute_offset);
if (optv > 1) { if (optv > 1) {
lcn = le64_to_cpu(action->record.lcn_list[0]); lcn = sle64_to_cpu(action->record.lcn_list[0]);
printf("-> inode %lld lcn 0x%llx target 0x%x length %d\n", printf("-> inode %lld lcn 0x%llx target 0x%x length %d\n",
(long long)inode_number(&action->record), (long long)inode_number(&action->record),
(long long)lcn, (int)target, (int)length); (long long)lcn, (int)target, (int)length);
} }
if (optv > 1) { if (optv > 1) {
printf("-> existing record :\n"); printf("-> existing record :\n");
dump(buffer,mftrecsz); dump(buffer,mftrecsz);
} }
record = (MFT_RECORD*)buffer; record = (MFT_RECORD*)buffer;
if ((target + length) <= mftrecsz) { if ((target + length) <= mftrecsz) {
skipping to change at line 3359 skipping to change at line 3360
firstbit = le32_to_cpu(data->firstbit); firstbit = le32_to_cpu(data->firstbit);
count = le32_to_cpu(data->count); count = le32_to_cpu(data->count);
if (action->record.redo_operation if (action->record.redo_operation
== const_cpu_to_le16(SetBitsInNonResidentBitMap)) == const_cpu_to_le16(SetBitsInNonResidentBitMap))
wanted = 0; wanted = 0;
else else
wanted = 1; wanted = 1;
// TODO consistency undo_offset == redo_offset, etc. // TODO consistency undo_offset == redo_offset, etc.
// firstbit + count < 8*clustersz (multiple clusters possible ?) // firstbit + count < 8*clustersz (multiple clusters possible ?)
if (optv > 1) { if (optv > 1) {
lcn = le64_to_cpu(action->record.lcn_list[0]); lcn = sle64_to_cpu(action->record.lcn_list[0]);
printf("-> lcn 0x%llx firstbit %d count %d wanted %d\n", printf("-> lcn 0x%llx firstbit %d count %d wanted %d\n",
(long long)lcn,(int)firstbit,(int)count,(int)wanted); (long long)lcn,(int)firstbit,(int)count,(int)wanted);
} }
for (i=0; i<count; i++) for (i=0; i<count; i++)
ntfs_bit_set((u8*)buffer, firstbit + i, wanted); ntfs_bit_set((u8*)buffer, firstbit + i, wanted);
if (!write_raw(vol, &action->record, buffer)) { if (!write_raw(vol, &action->record, buffer)) {
err = 0; err = 0;
if (optv > 1) if (optv > 1)
printf("-> record updated\n"); printf("-> record updated\n");
} }
if (err) if (err)
printf("** redo_clearbits failed\n"); printf("** redo_clearbits failed\n");
return (err); return (err);
} }
static int undo_open_attribute(ntfs_volume *vol __attribute__((unused)), static int undo_open_attribute(ntfs_volume *vol __attribute__((unused)),
const struct ACTION_RECORD *action) const struct ACTION_RECORD *action)
{ {
const char *data; const char *data;
struct ATTR *pa; struct ATTR *pa;
const struct ATTR_OLD *attr_old; const ATTR_OLD *attr_old;
const struct ATTR_NEW *attr_new; const ATTR_NEW *attr_new;
const char *name; const char *name;
le64 inode; le64 inode;
u32 namelen; u32 namelen;
u32 length; u32 length;
u32 extra; u32 extra;
int err; int err;
if (optv > 1) if (optv > 1)
printf("-> %s()\n",__func__); printf("-> %s()\n",__func__);
err = 1; err = 1;
skipping to change at line 3416 skipping to change at line 3417
} }
} else { } else {
namelen = 0; namelen = 0;
name = ""; name = "";
} }
pa = getattrentry(le16_to_cpu(action->record.target_attribute),0); pa = getattrentry(le16_to_cpu(action->record.target_attribute),0);
// TODO Only process is attr is not older ? // TODO Only process is attr is not older ?
if (pa) { if (pa) {
/* check whether the redo attr matches what we have in store */ /* check whether the redo attr matches what we have in store */
switch (length) { switch (length) {
case sizeof(struct ATTR_OLD) : case sizeof(ATTR_OLD) :
attr_old = (const struct ATTR_OLD*)data; attr_old = (const ATTR_OLD*)data;
/* Badly aligned */ /* Badly aligned */
memcpy(&inode, &attr_old->inode, 8); memcpy(&inode, &attr_old->inode, 8);
err = (MREF(le64_to_cpu(inode)) != pa->inode) err = (MREF(le64_to_cpu(inode)) != pa->inode)
|| (attr_old->type != pa->type); || (attr_old->type != pa->type);
break; break;
case sizeof(struct ATTR_NEW) : case sizeof(ATTR_NEW) :
attr_new = (const struct ATTR_NEW*)data; attr_new = (const ATTR_NEW*)data;
err = (MREF(le64_to_cpu(attr_new->inode))!= pa->inode) err = (MREF(le64_to_cpu(attr_new->inode))!= pa->inode)
|| (attr_new->type != pa->type); || (attr_new->type != pa->type);
break; break;
default : err = 1; default : err = 1;
} }
if (!err) { if (!err) {
err = (namelen != pa->namelen) err = (namelen != pa->namelen)
|| (namelen || (namelen
&& memcmp(name, pa->name, namelen)); && memcmp(name, pa->name, namelen));
} }
skipping to change at line 3526 skipping to change at line 3527
if (optv > 1) if (optv > 1)
printf("-> %s()\n",__func__); printf("-> %s()\n",__func__);
err = 1; err = 1;
data = ((const char*)&action->record) data = ((const char*)&action->record)
+ get_undo_offset(&action->record); + get_undo_offset(&action->record);
length = le16_to_cpu(action->record.undo_length); length = le16_to_cpu(action->record.undo_length);
target = le16_to_cpu(action->record.record_offset) target = le16_to_cpu(action->record.record_offset)
+ le16_to_cpu(action->record.attribute_offset); + le16_to_cpu(action->record.attribute_offset);
if (optv > 1) { if (optv > 1) {
lcn = le64_to_cpu(action->record.lcn_list[0]); lcn = sle64_to_cpu(action->record.lcn_list[0]);
printf("-> lcn 0x%llx target 0x%x length %d\n", printf("-> lcn 0x%llx target 0x%x length %d\n",
(long long)lcn, (int)target, (int)length); (long long)lcn, (int)target, (int)length);
} }
if (optv > 1) { if (optv > 1) {
printf("-> existing record :\n"); printf("-> existing record :\n");
dump(&buffer[target], length); dump(&buffer[target], length);
} }
if ((target + length) <= vol->indx_record_size) { if ((target + length) <= vol->indx_record_size) {
changed = length && memcmp(buffer + target, data, length); changed = length && memcmp(buffer + target, data, length);
err = 0; err = 0;
skipping to change at line 3602 skipping to change at line 3603
if (optv > 1) if (optv > 1)
printf("-> %s()\n",__func__); printf("-> %s()\n",__func__);
err = 1; err = 1;
data = ((const char*)&action->record) data = ((const char*)&action->record)
+ get_undo_offset(&action->record); + get_undo_offset(&action->record);
length = le16_to_cpu(action->record.undo_length); length = le16_to_cpu(action->record.undo_length);
resize = length - le16_to_cpu(action->record.redo_length); resize = length - le16_to_cpu(action->record.redo_length);
target = le16_to_cpu(action->record.record_offset) target = le16_to_cpu(action->record.record_offset)
+ le16_to_cpu(action->record.attribute_offset); + le16_to_cpu(action->record.attribute_offset);
if (optv > 1) { if (optv > 1) {
lcn = le64_to_cpu(action->record.lcn_list[0]); lcn = sle64_to_cpu(action->record.lcn_list[0]);
printf("-> inode %lld lcn 0x%llx target 0x%x new length %d resize %d\n", printf("-> inode %lld lcn 0x%llx target 0x%x new length %d resize %d\n",
(long long)inode_number(&action->record), (long long)inode_number(&action->record),
(long long)lcn, (int)target, (int)length, (int)resize); (long long)lcn, (int)target, (int)length, (int)resize);
} }
// TODO share with redo_update_mapping() // TODO share with redo_update_mapping()
if (optv > 1) { if (optv > 1) {
printf("-> existing record :\n"); printf("-> existing record :\n");
dump(&buffer[target], length); dump(&buffer[target], length);
} }
entry = (MFT_RECORD*)buffer; entry = (MFT_RECORD*)buffer;
skipping to change at line 3694 skipping to change at line 3695
undo = get_undo_offset(&action->record); undo = get_undo_offset(&action->record);
if ((undo + length) > end) if ((undo + length) > end)
data = (char*)NULL; data = (char*)NULL;
else else
data = ((const char*)&action->record) + undo; data = ((const char*)&action->record) + undo;
oldlength = le16_to_cpu(action->record.redo_length); oldlength = le16_to_cpu(action->record.redo_length);
target = le16_to_cpu(action->record.record_offset) target = le16_to_cpu(action->record.record_offset)
+ le16_to_cpu(action->record.attribute_offset); + le16_to_cpu(action->record.attribute_offset);
if (length == oldlength) { if (length == oldlength) {
if (optv > 1) { if (optv > 1) {
lcn = le64_to_cpu(action->record.lcn_list[0]); lcn = sle64_to_cpu(action->record.lcn_list[0]);
printf("-> inode %lld lcn 0x%llx target 0x%x length %d\n" , printf("-> inode %lld lcn 0x%llx target 0x%x length %d\n" ,
(long long)inode_number(&action->record), (long long)inode_number(&action->record),
(long long)lcn, (int)target, (int)length); (long long)lcn, (int)target, (int)length);
} }
if (optv > 1) { if (optv > 1) {
printf("-> existing record :\n"); printf("-> existing record :\n");
dump(&buffer[target], length); dump(&buffer[target], length);
} }
if ((target + length) <= mftrecsz) { if ((target + length) <= mftrecsz) {
changed = memcmp(buffer + target, data, length); changed = memcmp(buffer + target, data, length);
skipping to change at line 3805 skipping to change at line 3806
if (optv > 1) if (optv > 1)
printf("-> %s()\n",__func__); printf("-> %s()\n",__func__);
err = 1; err = 1;
data = ((const char*)&action->record) data = ((const char*)&action->record)
+ get_undo_offset(&action->record); + get_undo_offset(&action->record);
length = le16_to_cpu(action->record.undo_length); length = le16_to_cpu(action->record.undo_length);
target = le16_to_cpu(action->record.record_offset) target = le16_to_cpu(action->record.record_offset)
+ le16_to_cpu(action->record.attribute_offset); + le16_to_cpu(action->record.attribute_offset);
count = le16_to_cpu(action->record.lcns_to_follow); count = le16_to_cpu(action->record.lcns_to_follow);
if (optv > 1) { if (optv > 1) {
lcn = le64_to_cpu(action->record.lcn_list[0]); lcn = sle64_to_cpu(action->record.lcn_list[0]);
printf("-> lcn 0x%llx target 0x%x length %d\n", printf("-> lcn 0x%llx target 0x%x length %d\n",
(long long)lcn, (int)target, (int)length); (long long)lcn, (int)target, (int)length);
} }
if (length) { if (length) {
if (optv > 1) { if (optv > 1) {
printf("-> existing record :\n"); printf("-> existing record :\n");
dump(&buffer[target], length); dump(&buffer[target], length);
} }
if ((target + length) <= (count << clusterbits)) { if ((target + length) <= (count << clusterbits)) {
changed = memcmp(buffer + target, data, length); changed = memcmp(buffer + target, data, length);
skipping to change at line 3873 skipping to change at line 3874
undo = get_undo_offset(&action->record); undo = get_undo_offset(&action->record);
if ((undo + length) > end) if ((undo + length) > end)
data = (char*)NULL; data = (char*)NULL;
else else
data = ((const char*)&action->record) + undo; data = ((const char*)&action->record) + undo;
oldlength = le16_to_cpu(action->record.redo_length); oldlength = le16_to_cpu(action->record.redo_length);
target = le16_to_cpu(action->record.record_offset) target = le16_to_cpu(action->record.record_offset)
+ le16_to_cpu(action->record.attribute_offset); + le16_to_cpu(action->record.attribute_offset);
if (length == oldlength) { if (length == oldlength) {
if (optv > 1) { if (optv > 1) {
lcn = le64_to_cpu(action->record.lcn_list[0]); lcn = sle64_to_cpu(action->record.lcn_list[0]);
printf("-> inode %lld lcn 0x%llx target 0x%x" printf("-> inode %lld lcn 0x%llx target 0x%x"
" length %d\n", " length %d\n",
(long long)inode_number(&action->record), (long long)inode_number(&action->record),
(long long)lcn, (int)target, (int)length); (long long)lcn, (int)target, (int)length);
} }
if (optv > 1) { if (optv > 1) {
printf("-> existing record :\n"); printf("-> existing record :\n");
dump(&buffer[target], length); dump(&buffer[target], length);
} }
if ((target + length) <= mftrecsz) { if ((target + length) <= mftrecsz) {
skipping to change at line 3940 skipping to change at line 3941
undo = get_undo_offset(&action->record); undo = get_undo_offset(&action->record);
if ((undo + length) > end) if ((undo + length) > end)
data = (char*)NULL; data = (char*)NULL;
else else
data = ((const char*)&action->record) + undo; data = ((const char*)&action->record) + undo;
oldlength = le16_to_cpu(action->record.redo_length); oldlength = le16_to_cpu(action->record.redo_length);
target = le16_to_cpu(action->record.record_offset) target = le16_to_cpu(action->record.record_offset)
+ le16_to_cpu(action->record.attribute_offset); + le16_to_cpu(action->record.attribute_offset);
if (length == oldlength) { if (length == oldlength) {
if (optv > 1) { if (optv > 1) {
lcn = le64_to_cpu(action->record.lcn_list[0]); lcn = sle64_to_cpu(action->record.lcn_list[0]);
printf("-> inode %lld lcn 0x%llx target 0x%x" printf("-> inode %lld lcn 0x%llx target 0x%x"
" length %d\n", " length %d\n",
(long long)inode_number(&action->record), (long long)inode_number(&action->record),
(long long)lcn, (int)target, (int)length); (long long)lcn, (int)target, (int)length);
} }
if (optv > 1) { if (optv > 1) {
printf("-> existing record :\n"); printf("-> existing record :\n");
dump(&buffer[target], length); dump(&buffer[target], length);
} }
if ((target + length) <= mftrecsz) { if ((target + length) <= mftrecsz) {
skipping to change at line 3992 skipping to change at line 3993
struct ATTR *pa; struct ATTR *pa;
const char *data; const char *data;
enum ACTION_KIND kind; enum ACTION_KIND kind;
/* /*
* If we are sure the action was defined by Vista * If we are sure the action was defined by Vista
* or subsequent, just use attribute_flags. * or subsequent, just use attribute_flags.
* Unfortunately, only on some cases we can determine * Unfortunately, only on some cases we can determine
* the action was defined by Win10 (or subsequent). * the action was defined by Win10 (or subsequent).
*/ */
if (action->record.log_record_flags if (action->record.log_record_flags
& const_cpu_to_le16(RECORD_DELETING | RECORD_ADDING)) { & (LOG_RECORD_DELETING | LOG_RECORD_ADDING)) {
if (action->record.attribute_flags if (action->record.attribute_flags & ACTS_ON_INDX)
& const_cpu_to_le16(ACTS_ON_INDX))
kind = ON_INDX; kind = ON_INDX;
else else
if (action->record.attribute_flags if (action->record.attribute_flags & ACTS_ON_MFT)
& const_cpu_to_le16(ACTS_ON_MFT))
kind = ON_MFT; kind = ON_MFT;
else else
kind = ON_RAW; kind = ON_RAW;
} else { } else {
/* /*
* In other cases, we have to rely on the attribute * In other cases, we have to rely on the attribute
* definition, but this has defects when undoing. * definition, but this has defects when undoing.
*/ */
pa = getattrentry(le16_to_cpu( pa = getattrentry(le16_to_cpu(
action->record.target_attribute),0); action->record.target_attribute),0);
skipping to change at line 4325 skipping to change at line 4324
default : default :
err = 1; err = 1;
kind = ON_NONE; kind = ON_NONE;
break; break;
} }
executed = FALSE; executed = FALSE;
switch (kind) { switch (kind) {
case ON_MFT : case ON_MFT :
/* /*
the check below cannot be used on WinXP the check below cannot be used on WinXP
if (!(action->record.attribute_flags & const_cpu_to_le16(ACTS_ON_MFT))) if (!(action->record.attribute_flags & ACTS_ON_MFT))
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) ;
*/ */
/* Check whether data is to be discarded */ /* Check whether data is to be discarded */
warn = (rop != InitializeFileRecordSegment) warn = (rop != InitializeFileRecordSegment)
|| !check_full_mft(action,TRUE); || !check_full_mft(action,TRUE);
buffer = read_protected(vol, &action->record, buffer = read_protected(vol, &action->record,
mftrecsz, warn); mftrecsz, warn);
entry = (MFT_RECORD*)buffer; entry = (MFT_RECORD*)buffer;
if (entry && (entry->magic == magic_FILE)) { if (entry && (entry->magic == magic_FILE)) {
data_lsn = sle64_to_cpu(entry->lsn); data_lsn = sle64_to_cpu(entry->lsn);
skipping to change at line 4366 skipping to change at line 4365
" acting on MFT\n", " acting on MFT\n",
actionname(rop), actionname(rop),
(int)action->num); (int)action->num);
err = 1; err = 1;
} }
} }
break; break;
case ON_INDX : case ON_INDX :
/* /*
the check below cannot be used on WinXP the check below cannot be used on WinXP
if (!(action->record.attribute_flags & const_cpu_to_le16(ACTS_ON_INDX))) if (!(action->record.attribute_flags & ACTS_ON_INDX))
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 );
*/ */
xsize = vol->indx_record_size; xsize = vol->indx_record_size;
/* Check whether data is to be discarded */ /* Check whether data is to be discarded */
warn = (rop != UpdateNonResidentValue) warn = (rop != UpdateNonResidentValue)
|| !check_full_index(action,TRUE); || !check_full_index(action,TRUE);
buffer = read_protected(vol, &action->record, buffer = read_protected(vol, &action->record,
xsize, warn); xsize, warn);
indx = (INDEX_BLOCK*)buffer; indx = (INDEX_BLOCK*)buffer;
if (indx && (indx->magic == magic_INDX)) { if (indx && (indx->magic == magic_INDX)) {
skipping to change at line 4407 skipping to change at line 4406
printf("** %s (action %d) not" printf("** %s (action %d) not"
" acting on INDX\n", " acting on INDX\n",
actionname(rop), actionname(rop),
(int)action->num); (int)action->num);
err = 1; err = 1;
} }
} }
break; break;
case ON_RAW : case ON_RAW :
if (action->record.attribute_flags if (action->record.attribute_flags
& (const_cpu_to_le16(ACTS_ON_INDX | ACTS_ON_MFT))) { & (ACTS_ON_INDX | ACTS_ON_MFT)) {
printf("** Error : action %s on MFT" printf("** Error : action %s on MFT"
" or INDX\n", " or INDX\n",
actionname(rop)); actionname(rop));
err = 1; err = 1;
} else { } else {
buffer = read_raw(vol, &action->record); buffer = read_raw(vol, &action->record);
if (!buffer) if (!buffer)
err = 1; err = 1;
} }
break; break;
skipping to change at line 4706 skipping to change at line 4705
case UpdateRecordDataRoot : case UpdateRecordDataRoot :
case Win10Action35 : case Win10Action35 :
case Win10Action36 : case Win10Action36 :
kind = ON_NONE; kind = ON_NONE;
break; break;
} }
switch (kind) { switch (kind) {
case ON_MFT : case ON_MFT :
/* /*
the check below cannot be used on WinXP the check below cannot be used on WinXP
if (!(action->record.attribute_flags & const_cpu_to_le16(ACTS_ON_MFT))) if (!(action->record.attribute_flags & ACTS_ON_MFT))
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) ;
*/ */
buffer = read_protected(vol, &action->record, mftrecsz, TRUE); buffer = read_protected(vol, &action->record, mftrecsz, TRUE);
entry = (MFT_RECORD*)buffer; entry = (MFT_RECORD*)buffer;
if (entry) { if (entry) {
if (entry->magic == magic_FILE) { if (entry->magic == magic_FILE) {
executed = !older_record(entry, executed = !older_record(entry,
&action->record); &action->record);
if (!executed if (!executed
&& exception(action->num)) && exception(action->num))
skipping to change at line 4730 skipping to change at line 4729
(long long)sle64_to_cpu(entry->lsn), (long long)sle64_to_cpu(entry->lsn),
(executed ? "not older" : "older"), (executed ? "not older" : "older"),
(int)action->num, (int)action->num,
(long long)sle64_to_cpu(action->record.this_lsn)); (long long)sle64_to_cpu(action->record.this_lsn));
} else { } else {
printf("** %s (action %d) not acting on MFT\n", printf("** %s (action %d) not acting on MFT\n",
actionname(rop), (int)action->num); actionname(rop), (int)action->num);
err = 1; err = 1;
} }
} else { } else {
/* Undoing a record create which was not done ? */ /*
// TODO make sure this is about a newly allocated record (with bad fixup) * Could not read the MFT record :
// TODO check this is inputting a full record (record lth == data lth) * if this is undoing a record create (from scratch)
buffer = (char*)calloc(1, mftrecsz); * which did not take place, there is nothing to redo,
* otherwise this is an error.
*/
if (check_full_mft(action,TRUE))
executed = FALSE;
else
err = 1;
} }
break; break;
case ON_INDX : case ON_INDX :
/* /*
the check below cannot be used on WinXP the check below cannot be used on WinXP
if (!(action->record.attribute_flags & const_cpu_to_le16(ACTS_ON_INDX))) if (!(action->record.attribute_flags & ACTS_ON_INDX))
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 );
*/ */
xsize = vol->indx_record_size; 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; indx = (INDEX_BLOCK*)buffer;
if (indx) { if (indx) {
if (indx->magic == magic_INDX) { if (indx->magic == magic_INDX) {
executed = !older_record(indx, executed = !older_record(indx,
&action->record); &action->record);
if (!executed if (!executed
skipping to change at line 4764 skipping to change at line 4769
(long long)sle64_to_cpu(indx->lsn), (long long)sle64_to_cpu(indx->lsn),
(executed ? "not older" : "older"), (executed ? "not older" : "older"),
(int)action->num, (int)action->num,
(long long)sle64_to_cpu(action->record.this_lsn)); (long long)sle64_to_cpu(action->record.this_lsn));
} else { } else {
printf("** %s (action %d) not acting on INDX\n", printf("** %s (action %d) not acting on INDX\n",
actionname(rop), (int)action->num); actionname(rop), (int)action->num);
err = 1; err = 1;
} }
} else { } else {
/* Undoing a record create which was not done ? */ /*
// TODO make sure this is about a newly allocated record (with bad fixup) * Could not read the INDX record :
// TODO check this is inputting a full record (record lth == data lth) * if this is undoing a record create (from scratch)
// recreate an INDX record if this is the first entry * which did not take place, there is nothing to redo,
buffer = (char*)calloc(1, xsize); * otherwise this must be an error.
err = create_indx(vol, action, buffer); * However, after deleting the last index allocation
executed = TRUE; * in a block, the block is apparently zeroed
* and cannot be read. In this case we have to
* create an initial index block and apply the undo.
*/
if (check_full_index(action,TRUE))
executed = FALSE;
else {
err = 1;
if (uop == AddIndexEntryAllocation) {
executed = TRUE;
buffer = (char*)calloc(1, xsize);
if (buffer)
err = create_indx(vol,
action, buffer);
}
}
} }
break; break;
case ON_RAW : case ON_RAW :
if (action->record.attribute_flags if (action->record.attribute_flags
& (const_cpu_to_le16(ACTS_ON_INDX | ACTS_ON_MFT))) { & (ACTS_ON_INDX | ACTS_ON_MFT)) {
printf("** Error : action %s on MFT or INDX\n", printf("** Error : action %s on MFT or INDX\n",
actionname(rop)); actionname(rop));
err = 1; err = 1;
} else { } else {
buffer = read_raw(vol, &action->record); buffer = read_raw(vol, &action->record);
if (!buffer) if (!buffer)
err = 1; err = 1;
} }
executed = TRUE; executed = TRUE;
break; break;
 End of changes. 68 change blocks. 
86 lines changed or deleted 106 lines changed or added

Home  |  About  |  All  |  Newest  |  Fossies Dox  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTPS