usnjournal监控

  • 概述
  • 三、图解
    • 1:判断元数据$usnjournal是否存在
    • 2:保存所有需要的信息
    • 3:定位到监控的位置
  • 四、代码实现

首页

概述

1:百度百科
2:USN 日志( 更新序列号日志)或更改日志[ 1]是 Windows NT 文件系统 ( NTFS )的一项功能,它维护对卷所做更改的记录。不要将它与用于NTFS 文件系统日志的日志相混淆。

当Windows 2000发布时,Microsoft创建了NTFS版本 3.0,其中包括几个新功能和对旧版本文件系统的改进。其中之一是对某些类型的应用程序非常有用的新系统管理功能。在 Windows 2000 下,可以设置 NTFS 3.0分区来跟踪卷上文件和目录的更改,提供对各种对象执行的时间和操作的记录。启用后,系统会在 USN 日志中记录对卷所做的所有更改,该名称也用于描述功能本身。

为每个 NTFS 卷维护一个日志并存储在名为 $Extend$UsnJrnl的NTFS 元文件中。它以一个空文件开始。每当对卷进行更改时,都会将一条记录添加到文件中。每条记录由64 位更新序列号或 USN 标识(因此更改日志有时称为 USN 日志)。Change Journal 中的每条记录都包含 USN、文件的名称以及有关更改内容的信息。

更改日志使用位标志(例如 USN_REASON_DATA_OVERWRITE [2])描述发生的更改,因此它不包括与更改相关的所有数据或详细信息。因此,更改日志不能用于撤消对 NTFS 内文件的操作。维基百科
3:usnjournal结构
4:属性

三、图解

1:判断元数据$usnjournal是否存在

如果$ usnjournal不存在(一般刚刚初始化或者新建盘符),这个时候创建$usnjournal,否则就没办法监控usnjournal。

//%1 : 盘符bool isOk = QProcess::startDetached("cmd", QStringList() << "/c" << QString("fsutil usn createjournal m=33554432 a=8388608 %1:").arg(m_partitionName.at(0)));

fsutil usn使用方法

2:保存所有需要的信息

后面还有两个$J,不在一一列出。

3:定位到监控的位置

四、代码实现

//获取usnJournal基本信息
bool CNtfsInfo::_getUsnJournalBasicInfo(S_MFT_USN_JOURNAL& usnJournalBasicInfo,QByteArray byteData)
{S_FILE_RECORD fileRecordHead;//文件头bool isOk = NTFS_MFTFileHeader(fileRecordHead,byteData);if(!isOk)return false;quint32 allLength = fileRecordHead.BytesInUse-4;//所有属性的大小quint32 byteOffset = fileRecordHead.AttributeOffset;int whileCount = allLength ;while(byteOffset<allLength ){if((--whileCount) == 0){        //死循环异常NTFS_setErrorType(CNTFS::WhileError);return false;}if(!(byteData.mid(byteOffset,sizeof (quint32)).toHex()).compare("FFFFFFFF",Qt::CaseInsensitive))return true;S_USN_JOURNAL_ATTRIBUTE_HEADER attH;//属性头qint8 NonResidentFlag = NTFS_MFTUsnAtt(attH,byteData.mid(byteOffset,sizeof(S_USN_JOURNAL_ATTRIBUTE_HEADER)));//获取属性 返回0常驻,1非常驻,-1:失败if(NonResidentFlag == -1)return false;switch(attH.AttributeType) {//0x20case AttributeAttributeList:{byteOffset += attH.NonResidentFlag==0 ? attH.CCommon.CResident.StreamOffset : attH.CCommon.CNonResident.RunListOffset;if(attH.NonResidentFlag==0 && (attH.AttributeLength - attH.CCommon.CResident.StreamOffset)>0) {QList<S_ATTRIBUTE_0X20> x20L = NTFS_0X20Att(byteData.mid(byteOffset,attH.AttributeLength - attH.CCommon.CResident.StreamOffset));for(int i=0;i<x20L.count();i++) {QList<MFTNUM> _temp;//只获取不同的mft 属性x80if((x20L.at(i).AttributeType == AttributeData ) && x20L.at(i).Fdir.FileReferenceNumber != fileRecordHead.MFTRecordNumber){if(!_temp.contains(x20L.at(i).Fdir.FileReferenceNumber)) {      //以防多次执行,不同的mft只执行一次_temp.append(x20L.at(i).Fdir.FileReferenceNumber);quint64 offset = getMTFOffset(x20L.at(i).Fdir.FileReferenceNumber);QByteArray data = getRawData(m_NTFSOffset + offset,BYTES_PER_MFT_FILE);if(data.isNull())return false;bool isOk = _getUsnJournalBasicInfo( usnJournalBasicInfo,data);if(!isOk)return false;}}}byteOffset += (attH.AttributeLength-attH.CCommon.CResident.StreamOffset);} else if(attH.NonResidentFlag==1 && (attH.AttributeLength - attH.CCommon.CNonResident.RunListOffset)>0) {    //预防QList<S_DATARUN> DRunList;DRunList = NTFS_DatasRun(byteData.mid(byteOffset,attH.AttributeLength - attH.CCommon.CNonResident.RunListOffset));for(int i=0;i<DRunList.count();i++) {QByteArray data = getRawData(m_NTFSOffset + DRunList[i].dataStartCluster * BYTES_PER_CLUSTER,attH.CCommon.CNonResident.StreamRealSize);if(!data.isNull()) {QList<S_ATTRIBUTE_0X20> x20L = NTFS_0X20Att(data);for(int i=0;i<x20L.count();i++){QList<MFTNUM> _temp;//只获取不同的mft 属性x10和x30和x80if((x20L.at(i).AttributeType == AttributeData ) && x20L.at(i).Fdir.FileReferenceNumber != fileRecordHead.MFTRecordNumber) {if(!_temp.contains(x20L.at(i).Fdir.FileReferenceNumber)){//以防多次执行,不同的mft只执行一次_temp.append(x20L.at(i).Fdir.FileReferenceNumber);quint64 offset = getMTFOffset(x20L.at(i).Fdir.FileReferenceNumber);QByteArray data = getRawData(m_NTFSOffset + offset,BYTES_PER_MFT_FILE);if(data.isNull())return false;bool isOk = _getUsnJournalBasicInfo( usnJournalBasicInfo,data);if(!isOk)return false;}}}}}byteOffset += (attH.AttributeLength - attH.CCommon.CNonResident.RunListOffset);}}break;//x30case AttributeFileName:{byteOffset += attH.NonResidentFlag==0 ? attH.CCommon.CResident.StreamOffset : attH.CCommon.CNonResident.RunListOffset;if(attH.NonResidentFlag==0 && (attH.AttributeLength - attH.CCommon.CResident.StreamOffset)>0) {S_ATTRIBUTE_0X30 x30;QByteArray dataName = NTFS_0X30AttName(x30,byteData.mid(byteOffset,attH.AttributeLength - attH.CCommon.CResident.StreamOffset));if(!dataName.isNull()) {if(dataName.compare("$UsnJrnl",Qt::CaseInsensitive)==0)usnJournalBasicInfo.ISOK = true;}byteOffset += (attH.AttributeLength-attH.CCommon.CResident.StreamOffset);} else if(attH.NonResidentFlag==1 && (attH.AttributeLength - attH.CCommon.CNonResident.RunListOffset)>0){//预防byteOffset += (attH.AttributeLength - attH.CCommon.CNonResident.RunListOffset);}}break;//0x80case AttributeData:{byteOffset += attH.NonResidentFlag==0 ? attH.CCommon.CResident.StreamOffset : attH.CCommon.CNonResident.RunListOffset;if(attH.NonResidentFlag==0 && (attH.AttributeLength - attH.CCommon.CResident.StreamOffset)>0){QString name = QString::fromWCharArray(attH.CCommon.CResident.CAttName,attH.AttributeNameLength);//QString ret2 = QString((QChar*)x30.Name, wcslen(x30.Name));if(name=="$Max") {errno_t err = memcpy_s(&usnJournalBasicInfo.MaxAtt,16,byteData.mid(byteOffset,16).data(),16);//返回值为0,拷贝成功if(err) {qDebug()<<m_name_uuid<<"memcpy_s拷贝错误码:"<<err;return false;}}byteOffset += (attH.AttributeLength-attH.CCommon.CResident.StreamOffset);} else if(attH.NonResidentFlag==1 && (attH.AttributeLength - attH.CCommon.CNonResident.RunListOffset)>0) {/** 获取属性名,可能存在偏移位置不同*/char dataTemp[100];memset(dataTemp,0,sizeof(dataTemp));errno_t err = memcpy_s(dataTemp,sizeof(dataTemp), &attH,sizeof (S_USN_JOURNAL_ATTRIBUTE_HEADER));//返回值为0,拷贝成功if(err) {qDebug()<<m_name_uuid<<"memcpy_s拷贝错误码:"<<err;return false;}QString name = QString::fromWCharArray((wchar_t *)&dataTemp[attH.ContentOffset],attH.AttributeNameLength);if(name=="$J"){usnJournalBasicInfo.JAtt.append(attH);QByteArray temp = byteData.mid(byteOffset,attH.AttributeLength - attH.CCommon.CNonResident.RunListOffset);QList<S_DATARUN> DRunList;DRunList = NTFS_DatasRun(byteData.mid(byteOffset,attH.AttributeLength - attH.CCommon.CNonResident.RunListOffset));if(!DRunList.isEmpty())usnJournalBasicInfo.lDRun.append(DRunList);byteOffset += (attH.AttributeLength - attH.CCommon.CNonResident.RunListOffset);}}}break;case 0xFFFFFFFF:return true;default:byteOffset += (attH.AttributeLength);break;}}return false;
}//获取usnJournal MFT信息
S_MFT_USN_JOURNAL CNtfsInfo::getUsnJournalBasicInfo()
{S_MFT_USN_JOURNAL usnJournalBasicInfo;usnJournalBasicInfo.ISOK = false;quint64 mftOffset = getMTFOffset($Extend$UsnJrnl);QByteArray mftByte_1 = getRawData(m_NTFSOffset + mftOffset,BYTES_PER_MFT_FILE);if(mftByte_1.isNull())return usnJournalBasicInfo;S_MFT_INFO mftInfo_1;bool mftInfo_1IsOk= NTFS_MFTFileInfo(mftInfo_1,mftByte_1);if(!mftInfo_1IsOk)return usnJournalBasicInfo;if(mftInfo_1._x90.isEmpty())return usnJournalBasicInfo;if(mftInfo_1._x90.at(0).first.NonResidentFlag != 0)return usnJournalBasicInfo;QList<QPair<S_INDEX_ROOT_ITEM_ATTRIBUTE_0X90,QString>> varData = mftInfo_1._x90.at(0).second._x90Body;if (varData.isEmpty())return usnJournalBasicInfo;for(int i=0;i<varData.count();i++){if(!varData.at(i).second.compare(QString("$UsnJrnl"),Qt::CaseInsensitive)) {quint64 mftOffset = getMTFOffset(varData.at(i).first.dir.MFTDirectoryFile);QByteArray mftByte_1 = getRawData(m_NTFSOffset + mftOffset,BYTES_PER_MFT_FILE);if(mftByte_1.isNull())return usnJournalBasicInfo;bool isOk = _getUsnJournalBasicInfo(usnJournalBasicInfo,mftByte_1);if(isOk)usnJournalBasicInfo.ISOK = true;else{qDebug()<<m_name_uuid<<"获取usnJournalMFT信息失败!";usnJournalBasicInfo.ISOK = false;return usnJournalBasicInfo;}for(int i=0;i<usnJournalBasicInfo.JAtt.count();){//获取有用的属性头if(QString::compare(QString::fromWCharArray(usnJournalBasicInfo.JAtt.at(i).CCommon.CNonResident.CNonAttName,usnJournalBasicInfo.JAtt.at(i).AttributeNameLength),"$J")){usnJournalBasicInfo.JAtt.removeAt(i);}else{i++;}}if(usnJournalBasicInfo.JAtt.isEmpty())return usnJournalBasicInfo;}}return usnJournalBasicInfo;
}//更新数据库
void CNtfsInfo::updataDataBaseV2(PUSN_RECORD_UNION usnRecordUnion,quint64 usnRecordOffset /*=0*/)
{//qDebug()<<m_name_uuid<<"Usn_V2";QString fileName = QString::fromWCharArray(usnRecordUnion->V2.FileName,usnRecordUnion->V2.FileNameLength/2);QScopedPointer<S_DATA_BODY> dataBody(new S_DATA_BODY);if(!dataBody)return;dataBody.data()->MFTNumber =  usnRecordUnion->V2.FileReferenceNumber;dataBody.data()->PMFTNumber =  usnRecordUnion->V2.ParentFileReferenceNumber;S_DATA_SUBSET aD;aD.guid = m_initDatasInfo.info.uuid;aD.reason = usnRecordUnion->V2.Reason;aD.usnOffset = usnRecordOffset;aD.mft = usnRecordUnion->V2.FileReferenceNumber;/*//0x00000100:捕捉创建文件或文件夹;0x80000200:捕捉删除文件;0x8000200:捕捉重命名文件 或者本盘剪切*** 0x01   -> 0x80000001  文件中覆盖数据 (文件字节大小不变)* 0x02   -> 0x80000002  文件中增加数据(从无到有)* 0x03   -> 0x80000003  文件中增加数据 (在原来的存在数据中增加数据)* 0x05   -> 0x80000005  文件中删除部分数据* 0x04   -> 0x80000004  文件中删除全部数据** 0x04   -> 0x8004  -> 0x80008004  粘贴一个空文件替换掉原来的文件* 0x04   -> 0x6 -> 0x7 -> 0x8007  -> 0x80008007  粘贴一个非空文件替换掉原来的文件*/if(!(LOG_PATH_PMft == dataBody.data()->PMFTNumber  || USN_RECORD_PATH_PMft == dataBody.data()->PMFTNumber ||DATA_UPDATE_PATH_PMft == dataBody.data()->PMFTNumber || RUN_LOG_PATH_PMft == dataBody.data()->PMFTNumber)){//log文件夹下的所有文件发生改变不采集S_USN_LOG array;array.dataTime = DATETIMS;array.partition = m_partitionName.toUtf8();array.usnOffset = QByteArray::number(usnRecordOffset, 10);array.mft = QByteArray::number((MFTNUM) usnRecordUnion->V2.FileReferenceNumber, 10);array.pMft = QByteArray::number((MFTNUM) usnRecordUnion->V2.ParentFileReferenceNumber, 10);array.usn = QByteArray::number(usnRecordUnion->V2.Usn, 10);array.reasonDataTime = GlobalFunction::getInstance()->FILETIMEToDateTime(usnRecordUnion->V2.TimeStamp.QuadPart);array.reason = QByteArray::number((quint32)usnRecordUnion->V2.Reason,10);array.attributes = QByteArray::number((quint32)usnRecordUnion->V2.FileAttributes,10);array.fileName = fileName.toUtf8();emit SignalUsnRecordLog(UsnRecordLog,QVariant::fromValue(array));//记录usn日志}switch (usnRecordUnion->V2.Reason) {case 0x00000100://捕捉创建 复制case 0x80002000://重命名文件  本盘剪切也是0x00002000case 0x80000200://捕捉删除文件case 0x80000001://文件中覆盖数据 (文件字节大小不变)case 0x80000002://文件中增加数据(从无到有)// break;case 0x80000003://文件中增加数据 (在原来的存在数据中增加数据)// break;case 0x80000004://文件中删除全部数据// break;case 0x80000005://文件中删除部分数据// break;case 0x80008004://粘贴一个空文件替换掉原来的文件// break;case 0x80008007://粘贴一个非空文件替换掉原来的文件{MFT_BASIC_INFO basicInfo;quint64 mftOffset = getMTFOffset(dataBody.data()->MFTNumber);QByteArray byteData = getRawData(m_NTFSOffset + mftOffset,BYTES_PER_MFT_FILE);if(byteData.isNull())return ;if(!getMFTBasicInfo(basicInfo,byteData))return;for(int i=0;i<basicInfo.fileL.count();i++)basicInfo.fileL.at(i)->bodyAtt = basicInfo.attBody;aD.dataBodyL = basicInfo.fileL;emit SignalDataBase(aD);//更新数据}return;default:break;}}
void CNtfsInfo::updataDataBaseV3(PUSN_RECORD_UNION usnRecordUnion)
{qDebug()<<m_name_uuid<<"Usn_V3";
}
void CNtfsInfo::updataDataBaseV4(PUSN_RECORD_UNION usnRecordUnion)
{qDebug()<<m_name_uuid<<"Usn_V4";
}
//监控usn记录
void CNtfsInfo::usnRecordMonitoring()
{qDebug()<<m_name_uuid<<"开启usn记录监控!";while (!QThread::currentThread()->isInterruptionRequested()) {if(m_mftUsnJournal.ISOK)usnStartRun(m_mftUsnJournal);while (!QThread::currentThread()->isInterruptionRequested() && MemoryPool::getInstance()->getSettingArgs().usnRecordNoMonitoring)QThread::sleep(1);QThread::sleep(1);CNtfsInfo::Error type = anewInitDrive();switch (type){case NoError:{qDebug()<<m_name_uuid<<"NoError:重新获取usnJournalMFT信息!";while (!QThread::currentThread()->isInterruptionRequested()){QThread::sleep(1);m_mftUsnJournal = getUsnJournalBasicInfo();if(!m_mftUsnJournal.ISOK)break;//判断后来的StreamAiiocSize和DataSize和类中的比较是否相等,相等表示,数据块未发生变化,继续采集//不相等表示,数据块发生变化,覆盖类中的usnjournal MFT信息,重新采集usnjournal记录if(m_mftUsnJournal.JAtt.isEmpty())continue;//必须大于lastUSNNumber 说明才有数据,不然一直循环获取usn,直到有数据。 等于说明,最后(0x228最大usnjournal日志大小)存在数据,需要重新获取最后if(m_mftUsnJournal.JAtt[0].CCommon.CNonResident.StreamRealSize >= m_lastUsnNumber) {m_firstAnew = false;break;}}}break;case InitError:{qDebug()<<m_name_uuid<<"InitError:重新初始化失败,结束线程.";return;}break;case AnewInit:{qDebug()<<m_name_uuid<<"AnewInit:重新初始化,获取所有数据,重新采集...";initData();}break;}}
}//开启usn采集
void CNtfsInfo::usnStartRun(S_MFT_USN_JOURNAL usnJour)
{qDebug()<<m_name_uuid<<"开始采集usn记录...";quint32 count_i = 0;quint64 USNoffset=0;//实际偏移地址lcnquint64 dataRunSize=0;//当前使用的数据块大小quint64 dataRunOffset=0;//当前使用的数据块的偏移地址vcn  (不能大于dataRunSize)quint64 tempSize = 0;//记录数据块总共大小//firstAnew为TRUE是第开启usnif(m_firstAnew)m_lastUsnNumber = usnJour.JAtt[0].CCommon.CNonResident.StreamRealSize;//获取要读取usn记录的位置for(int i=0;i<usnJour.lDRun.count();++i) {//累加数据块大小tempSize += usnJour.lDRun[i].datalengthCluster * BYTES_PER_CLUSTER;//数据块大小和最后一个usn相等,从下一个块读取if(tempSize == m_lastUsnNumber){//当相加的数据块大小等于usn号时,此时usn号时下一个块的开头,所以要验证下一个数据块是否存在if((++i)>=usnJour.lDRun.count())return ;//要读取的数据块偏移vcndataRunOffset = 0;//要读取的数据块大小vcndataRunSize = usnJour.lDRun[i].datalengthCluster * BYTES_PER_CLUSTER;//要读取的物理偏移地址lcnUSNoffset =  m_NTFSOffset + usnJour.lDRun[i].dataStartCluster * BYTES_PER_CLUSTER;break;} else if(tempSize > m_lastUsnNumber){   //数据块大小大于最后一个usn,从当前数据块读取//要读取的数据块偏移vcndataRunOffset = usnJour.lDRun[i].datalengthCluster * BYTES_PER_CLUSTER +  m_lastUsnNumber - tempSize;//要读取的数据块大小vcndataRunSize = usnJour.lDRun[i].datalengthCluster * BYTES_PER_CLUSTER;//要读取的物理偏移地址lcn  取扇区首地址才能正常读取数据USNoffset =  m_NTFSOffset + usnJour.lDRun[i].dataStartCluster * BYTES_PER_CLUSTER + dataRunOffset - (dataRunOffset % PAGE_USN_RECORD_SIZE);break;}}qDebug()<<m_name_uuid<<"UsnNumber:"+QString::number(m_lastUsnNumber)<<" --- Usn记录偏移:"+QString::number(USNoffset - m_NTFSOffset);while (dataRunOffset<dataRunSize && !QThread::currentThread()->isInterruptionRequested()){//不监控usnif(MemoryPool::getInstance()->getSettingArgs().usnRecordNoMonitoring)return;if(!m_fileHandle->seek(USNoffset))return ;QByteArray rawdata = m_fileHandle->read(PAGE_USN_RECORD_SIZE+1);//读取if(rawdata.size()!=PAGE_USN_RECORD_SIZE+1)return ;quint32 readSize=0;if((PAGE_USN_RECORD_SIZE - dataRunOffset % PAGE_USN_RECORD_SIZE) >= MAX_USN_REOCRD_SIZE)//判断要copy的字节大小readSize = MAX_USN_REOCRD_SIZE;elsereadSize = (PAGE_USN_RECORD_SIZE - dataRunOffset % PAGE_USN_RECORD_SIZE);//memcpy(m_usnRecordUnion,rawdata.mid(dataRunOffset % PAGE_USN_RECORD_SIZE,readSize).data(),readSize);errno_t err = memcpy_s(m_usnRecordUnion,MAX_USN_REOCRD_SIZE,rawdata.mid(dataRunOffset % PAGE_USN_RECORD_SIZE,readSize).data(),readSize);//返回值为0,拷贝成功if(err){qDebug()<<m_name_uuid<<"memcpy_s拷贝错误码:"<<err;return ;}if(m_usnRecordUnion->V2.Usn && !m_firstAnew && (quint64)m_usnRecordUnion->V2.Usn != m_lastUsnNumber)return ;if(!m_usnRecordUnion->Header.RecordLength){//当记录都为0的时候,表示没有数据,count_i++;if(count_i%50==0){  //连续n次数据为空给cpu腾出时间,进入休眠,给cpu腾出时间片,缓解cpu压力//qDebug()<<m_name_uuid<<"连续N次采集数据为空,重新初始化!";CNtfsInfo::Error error = anewInitDrive();if(error != NoError)return ;QThread::sleep(1);count_i =0;}//QThread::msleep(500);//源码调用的也是Windows下Sleep();//QThread::msleep(0);//给cpu腾出时间片,}/*//0x00000100:捕捉创建文件或文件夹;0x80000200:捕捉删除文件;0x8000200:捕捉重命名文件 或者本盘剪切*** 0x01   -> 0x80000001  文件中覆盖数据 (文件字节大小不变)* 0x02   -> 0x80000002  文件中增加数据(从无到有)* 0x03   -> 0x80000003  文件中增加数据 (在原来的存在数据中增加数据)* 0x05   -> 0x80000005  文件中删除部分数据* 0x04   -> 0x80000004  文件中删除全部数据** 0x04   -> 0x8004  -> 0x80008004  粘贴一个空文件替换掉原来的文件* 0x04   -> 0x6 -> 0x7 -> 0x8007  -> 0x80008007  粘贴一个非空文件替换掉原来的文件*/switch (m_usnRecordUnion->Header.MajorVersion) {case 0x2:{if(m_usnRecordUnion->V2.Reason == 0)//等于0读取的数据不是完整的,重新读取continue;updataDataBaseV2(m_usnRecordUnion,USNoffset + dataRunOffset % PAGE_USN_RECORD_SIZE - m_NTFSOffset);m_lastUsnNumber = m_usnRecordUnion->V2.Usn + m_usnRecordUnion->Header.RecordLength;//记录最后一个usn号}break;case 0x3:{updataDataBaseV3(m_usnRecordUnion);}break;case 0x4:{updataDataBaseV4(m_usnRecordUnion);}break;default:{//continue;}break;}dataRunOffset += m_usnRecordUnion->Header.RecordLength;quint32 temp = PAGE_USN_RECORD_SIZE - (dataRunOffset % PAGE_USN_RECORD_SIZE);//剩余的数据小于0x40,丢弃//0x40 == sizeof(USN_RECORD_V2) + (8 - sizeof(USN_RECORD_V2)%8) //8字节是一个硬盘一块数据的最小占用if(temp < 0x40) {USNoffset += PAGE_USN_RECORD_SIZE;dataRunOffset += temp;m_lastUsnNumber += temp;//记录最后一个usn号if(dataRunOffset  == dataRunSize)//数据读到最后了,存在丢弃最后的小于0x228个字节break;else if(dataRunOffset  > dataRunSize)//大于就抛出异常return ;}else if(!m_usnRecordUnion->Header.RecordLength  && temp<MAX_USN_REOCRD_SIZE){   //0x228最大usnjournal日志大小if(dataRunOffset + temp == dataRunSize){    //数据读到最后了,存在丢弃最后的小于0x228个字节S_MFT_USN_JOURNAL mftUsnJournal = getUsnJournalBasicInfo();//先获取usn记录管理 1if(!mftUsnJournal.ISOK){    //usnjournal 错误:  卷更改日志处于非活动状态。m_lastUsnNumber += temp;//记录最后一个usn号break;}if(mftUsnJournal.JAtt[0].CCommon.CNonResident.StreamRealSize >= m_lastUsnNumber ){m_firstAnew = false;m_lastUsnNumber += temp;//记录最后一个usn号break;}} else if(dataRunOffset + temp > dataRunSize){  //大于就抛出异常return ;}else if((quint8)rawdata.back()>0){m_lastUsnNumber += temp;//记录最后一个usn号dataRunOffset += temp;USNoffset += PAGE_USN_RECORD_SIZE;}}else if(temp == PAGE_USN_RECORD_SIZE && m_usnRecordUnion->Header.RecordLength != 0){USNoffset += PAGE_USN_RECORD_SIZE;}}return ;
}

上面代码用到的结构体,可在这里查找

NTFS -usnjournal监控相关推荐

  1. 【性能优化】小伙伴问我性能指标监控怎么做,这次我安排上了!!

    小伙伴的疑问 小伙伴:监控怎么做? 我:你指的是? 小伙伴:性能指标. 我:后面会专门写这些文章. 使用JMX监控Tomcat 关于监控的文章,先写些什么呢?想来想去,我们先来写一篇使用JMX监控To ...

  2. 谈谈NTFS数据流文件

    1.什么是NTFS数据流文件?      要了解NTFS流文件之前,你应该对NTFS文件系统有一定的了解, NTFS是微软Windows NT内核的系列操作系统支持的.一个特别为网络和磁盘配额.文件加 ...

  3. python系统监控_python psutil系统监控详解

    一.psutil模块: 1.psutil是一个跨平台库(http://pythonhosted.org/psutil/)能够轻松实现获取系统运行的进程和系统利用率(包括CPU.内存.磁盘.网络等)信息 ...

  4. linux 访问磁盘bin,zabbix应用之Low-level discovery监控磁盘IO

    zabbix自带的"Template OS Linux"模板支持监控已挂载的磁盘空间利用率,是利用LLD(Low-level discovery)实现的,却没有对磁盘IO监控.本篇 ...

  5. java windows系统监控_Windows资源监控工具大全

    在利用LoadRunner进行性能测试的时候,Windows服务器的资源是经常需要监控的对象.其实除了LoadRunner提供的计数器,似乎Window服务器并不像Unix或者Linux提供众多的性能 ...

  6. C# FileSystemWatcher 在监控文件夹和文件时的用法

    ********************************************************************************** 第一个文章: ********** ...

  7. linux ntfs chkdsk,ntfs格式磁盘提示无法运行chkdsk解决办法

    方法1: 进入安全模式进行检查整理. 方法2: 因为D盘是ntfs,在windows正常使用过程中无法被Chkdsk,所以你在windows中的命令提示行中使用chkdsk是没用的.但是程序应该会自动 ...

  8. linux 磁盘监控,9个在Linux中监视Linux磁盘分区和用法的工具

    在这篇文章中,我们将回顾一些Linux的命令行工具 ,你可以使用它来检查磁盘分区在Linux中. 监控存储设备空间使用情况是SysAdmin的最重要的任务之一,这有助于确保存储设备上有足够的可用空间, ...

  9. 【文件监控】之一:理解 ReadDirectoryChangesW part1

    理解 ReadDirectoryChangesW 原作者:Jim Beveridge 原文:http://qualapps.blogspot.com/2010/05/understanding-rea ...

最新文章

  1. php分享三十三:用php中的register_shutdown_function和fastcgi_finish_request
  2. Codechef SEAARC Sereja and Arcs (分块)
  3. springboot2.3.4集成EhCache缓存框架完整代码
  4. SSD浅层网络_目标检测SSD
  5. 曼哈顿距离最小生成树与莫队算法(总结)
  6. Arturia Prophet Mac音频插件:将Prophet 5,Prophet VS,Prophet Hybrid三种不同音乐合成器于一体
  7. mysql 外键_为什么大多数互联网公司不用外键约束
  8. linux rkt命令,rkt 1.13.0发布,CoreOS的容器引擎
  9. nologging与append测试
  10. 【Jvm】jvm -XX 参数 VM 调优参数
  11. 检错码之奇偶校验编码
  12. Graham-Scan小总结——toj2317 Wall
  13. ICDAR2017 Competition on Reading Chinese Text in the Wild(RCTW-17) 介绍
  14. 拓端tecdat|R语言特征选择——逐步回归
  15. 微信群控二次开发SDK
  16. 关于debian网卡驱动
  17. 实现原理 扫描枪_条码扫描枪的工作原理
  18. Django Rest framework (看完直接上手用)
  19. 关于大数据,需要你读懂的10个小故事
  20. android如何加密手机号码,手机如何加密?

热门文章

  1. LInux的网络设置之(Bridged)桥接模式
  2. 1375. 二进制字符串前缀一致的次数-前序遍历法
  3. ArcGIS中坐标转换与投影变换
  4. linux 用谷歌浏览器总是崩溃,谷歌浏览器显示喔唷崩溃啦(谷歌浏览器经常崩溃怎么办)...
  5. 员工信息表,增删查改程序
  6. [分享] 《步步为营封 Win7》--skyfree
  7. 柜台收取西联汇款经验(网友分享)
  8. [重新认识前端的第4天] html+css案例
  9. 各种有意思的Github项目收集,不断更新
  10. BI数据分析师工作说明