scrounge.c
来自「磁盘格式解读」· C语言 代码 · 共 659 行 · 第 1/2 页
C
659 行
if(g_verifyMode)
{
if(compareFileData(ofile, data, length) != 0)
RETWARNX("verify failed. read file data wrong.");
}
else
#endif
if(write(ofile, data, length) != (int32)length)
RETWARN("couldn't write data to output file");
dataSize -= length;
}
/* For non resident data it's a bit more involved */
else
{
datarun = ntfsx_attribute_getdatarun(attribdata);
nonres = (ntfs_attribnonresident*)attrhead;
/* Allocate a cluster for reading and writing */
ntfsx_cluster_reserve(&cluster, pi);
if(ntfsx_datarun_first(datarun))
{
do
{
/*
* In some cases NTFS sloppily leaves many extra
* data runs mapped for a file, so just cut out
* when that's the case
*/
if(dataSize == 0)
break;
/* Sparse clusters we just write zeros */
if(datarun->sparse)
{
memset(cluster.data, 0, cluster.size);
for(i = 0; i < datarun->length && dataSize; i++)
{
num = cluster.size;
if(dataSize < 0xFFFFFFFF && num > (uint32)dataSize)
num = (uint32)dataSize;
#ifdef _DEBUG
if(g_verifyMode)
{
if(compareFileData(ofile, cluster.data, num) != 0)
RETWARNX("verify failed. read file data wrong.");
}
else
#endif
if(write(ofile, cluster.data, num) != (int32)num)
err(1, "couldn't write to output file: " FC_PRINTF, basics.filename);
dataSize -= num;
}
}
/* Handle not sparse clusters */
else
{
if(pi->locks)
{
/* Add a location lock so any raw scrounging won't do
this cluster later */
addLocationLock(pi->locks, CLUSTER_TO_SECTOR(*pi, datarun->cluster),
CLUSTER_TO_SECTOR(*pi, datarun->cluster + datarun->length));
}
for(i = 0; i < datarun->length && dataSize; i++)
{
num = min(cluster.size, (uint32)dataSize);
dataSector = CLUSTER_TO_SECTOR(*pi, (datarun->cluster + i));
if(!ntfsx_cluster_read(&cluster, pi, dataSector, pi->device))
{
warn("couldn't read sector from disk");
break;
}
#ifdef _DEBUG
if(g_verifyMode)
{
if(compareFileData(ofile, cluster.data, num) != 0)
RETWARNX("verify failed. read file data wrong.");
}
else
#endif
if(write(ofile, cluster.data, num) != (int32)num)
err(1, "couldn't write to output file: " FC_PRINTF, basics.filename);
dataSize -= num;
}
}
}
while(ntfsx_datarun_next(datarun));
}
ntfsx_datarun_free(datarun);
datarun = NULL;
}
ntfsx_attribute_free(attribdata);
attribdata = NULL;
/* Cut out when there's extra clusters allocated */
if(dataSize == 0)
break;
}
if(!haddata)
RETWARNX("invalid mft record. no data attribute found");
if(dataSize != 0)
warnx("invalid mft record. couldn't find all data for file");
/*
* Now we write blanks for all the sparse non-inited data
* We might be able to just resize the file to the right
* size, but let's go the safe way and write out zeros
*/
if(sparseSize > 0)
{
ntfsx_cluster_reserve(&cluster, pi);
memset(cluster.data, 0, cluster.size);
while(sparseSize > 0)
{
num = cluster.size;
if(sparseSize < 0xFFFFFFFF && num > (uint32)sparseSize)
num = (uint32)sparseSize;
#ifdef _DEBUG
if(g_verifyMode)
{
if(compareFileData(ofile, cluster.data, num) != 0)
RETWARNX("verify failed. read file data wrong.");
}
else
#endif
if(write(ofile, cluster.data, num) != (int32)num)
err(1, "couldn't write to output file: " FC_PRINTF, basics.filename);
sparseSize -= num;
}
}
close(ofile);
ofile = -1;
#ifdef _DEBUG
if(!g_verifyMode)
#endif
{
setFileTime(basics.filename, &(basics.created),
&(basics.accessed), &(basics.modified));
setFileAttributes(basics.filename, basics.flags);
}
}
cleanup:
if(record)
ntfsx_record_free(record);
ntfsx_cluster_release(&cluster);
if(attribdata)
ntfsx_attribute_free(attribdata);
if(datarun)
ntfsx_datarun_free(datarun);
if(attrenum)
ntfsx_attrib_enum_free(attrenum);
if(ofile != -1)
close(ofile);
}
void scroungeMFT(partitioninfo* pi, ntfsx_mftmap* map)
{
ntfsx_record* record = NULL;
uint64 sector;
filebasics basics;
ntfs_recordheader* header;
/* Try and find the MFT at the given location */
sector = pi->mft + pi->first;
if(sector >= pi->end)
errx(2, "invalid mft. past end of partition");
record = ntfsx_record_alloc(pi);
/* Read the MFT record */
if(!ntfsx_record_read(record, sector, pi->device))
err(1, "couldn't read mft");
header = ntfsx_record_header(record);
ASSERT(header);
if(!(header->flags & kNTFS_RecFlagUse))
errx(2, "invalid mft. marked as not in use");
/* Load the MFT data runs */
if(!ntfsx_mftmap_load(map, record, pi->device))
err(1, "error reading in mft");
/* Try and get a file name out of the header */
processRecordFileBasics(pi, record, &basics);
if(fcscmp(basics.filename, kNTFS_MFTName))
errx(2, "invalid mft. wrong record");
fprintf(stderr, "[Processing MFT...]\n");
if(ntfsx_mftmap_length(map) == 0)
errx(1, "invalid mft. no records in mft");
ntfsx_record_free(record);
}
void scroungeUsingMFT(partitioninfo* pi)
{
uint64 numRecords = 0;
fchar_t dir[MAX_PATH];
ntfsx_mftmap map;
uint64 length;
uint64 sector;
uint64 i;
fprintf(stderr, "[Scrounging via MFT...]\n");
/* Save current directory away */
fc_getcwd(dir, MAX_PATH);
/* Get the MFT map ready */
memset(&map, 0, sizeof(map));
ntfsx_mftmap_init(&map, pi);
pi->mftmap = ↦
/*
* Make sure the MFT is actually where they say it is.
* This also fills in the valid cluster size if needed
*/
scroungeMFT(pi, &map);
length = ntfsx_mftmap_length(&map);
for(i = 1; i < length; i ++)
{
sector = ntfsx_mftmap_sectorforindex(&map, i);
if(sector == kInvalidSector)
{
warnx("invalid index in mft: %d", i);
continue;
}
/* Process the record */
processMFTRecord(pi, sector, 0);
/* Move to right output directory */
fc_chdir(dir);
}
pi->mftmap = NULL;
}
void scroungeUsingRaw(partitioninfo* pi)
{
byte buffSec[kSectorSize];
fchar_t dir[MAX_PATH + 1];
uint64 sec;
drivelocks locks;
int64 pos;
size_t sz;
uint32 magic = kNTFS_RecMagic;
fprintf(stderr, "[Scrounging raw records...]\n");
/* Save current directory away */
fc_getcwd(dir, MAX_PATH);
/* Get the locks ready */
memset(&locks, 0, sizeof(locks));
pi->locks = &locks;
/* Loop through sectors */
for(sec = pi->first; sec < pi->end; sec++)
{
if(checkLocationLock(&locks, sec))
continue;
/* Read the record */
pos = SECTOR_TO_BYTES(sec);
if(lseek64(pi->device, pos, SEEK_SET) == -1)
errx(1, "can't seek device to sector");
sz = read(pi->device, buffSec, kSectorSize);
if(sz == -1 || sz != kSectorSize)
{
warn("can't read drive sector");
continue;
}
/* Check beginning of sector for the magic signature */
if(!memcmp(&magic, &buffSec, sizeof(magic)))
{
/* Process the record */
processMFTRecord(pi, sec, 0);
}
/* Move to right output directory */
fc_chdir(dir);
}
pi->locks = NULL;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?