如何手写一个文件索引工具everything(第一章)

news2024/10/5 19:13:31

第一章(NTFS格式及USN日志)

背景介绍

  • Windows平台的Everything文件查找速度非常快,优势在于利用了NTFS的USN日志,以及Windows上的文件监测机制
  • 我们也可以仿照类似原理,通过查询USN日志、监测Windows平台文件修改、使用SQLite数据库存储文件节点,并提供文件信息查询功能
    在这里插入图片描述

项目仓库

  • https://gitee.com/alanosong/MiniThing

NTFS格式

  • NTFS(New Technology File System)是微软随Windows系统开发的一种文件格式,专门为网络和磁盘配额、文件加密等管理安全特性设计。比起FAT格式,NTFS属于一种较为新型的磁盘格式。
  • 比起FAT格式,NTFS文件格式支持更大的分区,可以达到2TB。而FAT32可支持的最大分区只有32GB。
  • NTFS可以更有效地管理磁盘空间,避免磁盘空间的浪费。NTFS采用了更小的簇组,利用率更高。
  • NTFS更加安全稳定。NTFS拥有许多安全性能方面的选项,还提供文件加密支持,保障数据的安全性。同时,NTFS还能有效阻止没有授权的用户访问文件。
  • NTFS可自动修复磁盘出错的信息。例如,在当Windows系统向NTFS分区写入文件时,会保留文件的一份拷贝,然后检查向磁盘中所写的文件是否与内存中的一致。如果出现不一致的情况,Windows就把相应的扇区标为坏扇区而不再使用它(簇重映射)。之后,Windows系统会通过内存中保留的文件重新拷贝写入磁盘。在磁盘读写发生错误时,NTFS会报告错误信息,并告知相应的应用程序数据已经丢失。

USN日志

  • USN Journal 相当于 NTFS 的秘书,为磁盘记录下改动的一切,并储存为 USN_RECORD 的格式。
  • 因此我们可以通过查询系统的USN日志,快速获取系统中的所有文件节点信息,并建立相应的数据库以供查询

相关代码

    1. 判断磁盘是否为NTFS格式,这是首要条件
BOOL MiniThing::IsNtfs(VOID)
{
    BOOL isNtfs = FALSE;
    char sysNameBuf[MAX_PATH] = { 0 };

    int len = WstringToChar(m_volumeName + L"\\", nullptr);
    char* pVol = new char[len];
    WstringToChar(m_volumeName + L"\\", pVol);

    BOOL status = GetVolumeInformationA(
        pVol,
        NULL,
        0,
        NULL,
        NULL,
        NULL,
        sysNameBuf,
        MAX_PATH);

    if (FALSE != status)
    {
        std::cout << "File system name : " << sysNameBuf << std::endl;

        if (0 == strcmp(sysNameBuf, "NTFS"))
        {
            isNtfs = true;
        }
        else
        {
            std::cout << "File system not NTFS format !!!" << std::endl;
            GetSystemError();
        }
    }

    return isNtfs;
}
    1. 控制系统生成USN记录,方便我们查询,这一步通过Win32的DeviceIoControl()接口来实现
HRESULT MiniThing::CreateUsn(VOID)
{
    HRESULT ret = S_OK;

    DWORD br;
    CREATE_USN_JOURNAL_DATA cujd;
    cujd.MaximumSize = 0;
    cujd.AllocationDelta = 0;
    BOOL status = DeviceIoControl(
        m_hVol,
        FSCTL_CREATE_USN_JOURNAL,
        &cujd,
        sizeof(cujd),
        NULL,
        0,
        &br,
        NULL);

    if (FALSE != status)
    {
        std::cout << "Create usn file success" << std::endl;
        ret = S_OK;
    }
    else
    {
        std::cout << "Create usn file failed" << std::endl;
        GetSystemError();
        ret = E_FAIL;
    }

    return ret;
}
    1. 查询系统生成的USN相关信息,为下一步获取具体的文件日志做准备
HRESULT MiniThing::QueryUsn(VOID)
{
    HRESULT ret = S_OK;

    DWORD br;
    BOOL status = DeviceIoControl(m_hVol,
        FSCTL_QUERY_USN_JOURNAL,
        NULL,
        0,
        &m_usnInfo,
        sizeof(m_usnInfo),
        &br,
        NULL);

    if (FALSE != status)
    {
        std::cout << "Query usn info success" << std::endl;
    }
    else
    {
        ret = E_FAIL;
        std::cout << "Query usn info failed" << std::endl;
        GetSystemError();
    }

    return ret;
}
    1. 查询具体的USN日志,其中包含了所有文件的节点信息,包括了文件节点的Reference Number,Parent Reference Number等等,其类似于一个父子链表,通过Reference Number指定了文件之间的父子关系(目录和目录内的文件)。此处获取所有文件节点信息后,还需要我们手动为所有节点排序,获得文件的详细路径.
HRESULT MiniThing::RecordUsn(VOID)
{
    MFT_ENUM_DATA med = { 0, 0, m_usnInfo.NextUsn };
    med.MaxMajorVersion = 2;
    // Used to record usn info, must big enough
    char buffer[0x1000];
    DWORD usnDataSize = 0;
    PUSN_RECORD pUsnRecord;

    // Find the first USN record
    // return a USN followed by zero or more change journal records, each in a USN_RECORD structure
    while (FALSE != DeviceIoControl(m_hVol,
        FSCTL_ENUM_USN_DATA,
        &med,
        sizeof(med),
        buffer,
        _countof(buffer),
        &usnDataSize,
        NULL))
    {
        DWORD dwRetBytes = usnDataSize - sizeof(USN);
        pUsnRecord = (PUSN_RECORD)(((PCHAR)buffer) + sizeof(USN));
        DWORD cnt = 0;

        while (dwRetBytes > 0)
        {
            // Here FileNameLength may count in bytes, and each wchar_t occupy 2 bytes
            wchar_t* pWchar = new wchar_t[pUsnRecord->FileNameLength / 2 + 1];
            memcpy(pWchar, pUsnRecord->FileName, pUsnRecord->FileNameLength);
            pWchar[pUsnRecord->FileNameLength / 2] = 0x00;
            // wcsncpy_s(pWchar, pUsnRecord->FileNameLength / 2, pUsnRecord->FileName, pUsnRecord->FileNameLength / 2);
            std::wstring fileNameWstr = WcharToWstring(pWchar);
            delete pWchar;

            UsnInfo usnInfo = { 0 };
            usnInfo.fileNameWstr = fileNameWstr;
            usnInfo.pParentRef = pUsnRecord->ParentFileReferenceNumber;
            usnInfo.pSelfRef = pUsnRecord->FileReferenceNumber;
            usnInfo.timeStamp = pUsnRecord->TimeStamp;

            m_usnRecordMap[usnInfo.pSelfRef] = usnInfo;

            // Get the next USN record
            DWORD recordLen = pUsnRecord->RecordLength;
            dwRetBytes -= recordLen;
            pUsnRecord = (PUSN_RECORD)(((PCHAR)pUsnRecord) + recordLen);
        }

        // Get next page USN record
        // from MSDN(http://msdn.microsoft.com/en-us/library/aa365736%28v=VS.85%29.aspx ):  
        // The USN returned as the first item in the output buffer is the USN of the next record number to be retrieved.  
        // Use this value to continue reading records from the end boundary forward.  
        med.StartFileReferenceNumber = *(USN*)&buffer;
    }

    return S_OK;
}
    1. 至此,所有文件节点信息已经获取,需要对于信息进行排序,下一章再叙述。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/419204.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

亚马逊卖家如何用facebook推广?

亚马逊作为全球最大的电商平台之一&#xff0c;吸引了大量的卖家和买家。对于亚马逊的卖家而言&#xff0c;如何进行有效的推广和引流成为了他们最关心的问题之一。其中&#xff0c;利用Facebook广告为亚马逊进行推广是一种较为常见的做法。 但是&#xff0c;亚马逊可以用Face…

springboot实现修改用户信息功能

目录 1、UserEntity层 2、UserMapper层 3、UserService层 4、UserController类 5、Postman测试 要实现修改用户信息的功能&#xff0c;需要编写对应的代码&#xff1a; 如&#xff1a; 在UserEntity中定义用户实体类的属性。 在UserMapper中编写修改用户的SQL语句&#…

【C++】哈希的应用 -- 布隆过滤器

文章目录一、布隆过滤器的引入二、哈希函数个数的选择三、布隆过滤器的实现四、布隆过滤器的应用五、布隆过滤器总结一、布隆过滤器的引入 我们在上一节中学习了 位图&#xff0c;知道了位图可以用来快速判断某个数据是否在一个集合中&#xff0c;但是位图有如下的缺点&#x…

Qemu虚拟机读取物理机的物理网卡的流量信息方法

项目背景&#xff1a; 比如我有三个项目 A&#xff0c;B&#xff0c;C&#xff1b;其中A项目部署在物理机上&#xff0c;B&#xff0c;C项目部署在 虚拟机V1,V2中&#xff0c;三个项目接口需要相互调用。 需要解决的问题点&#xff1a; 1&#xff0c;因为A&#xff0c;B&#x…

2016-2017 ACM-ICPC Nordic Collegiate Programming Contest (NCPC 2016)题解

2016-2017 ACM-ICPC Nordic Collegiate Programming Contest (NCPC 2016) A - Artwork 题目描述&#xff1a; 给定N*M的网格&#xff0c;给出Q次询问&#xff0c;每次询问都给出一个小矩阵&#xff0c;保证每个矩阵要么长为1&#xff0c;要么宽为1&#xff0c;将网格中矩阵部…

最近给shopify跨境电商网站搞google搜索引擎的seo优化,整理了一些内容

接到一个网站&#xff0c;首先要做一些工作&#xff0c;然后按照这个步骤做好每一步&#xff0c;网站的搜索排名会有明显的效果。 对网站进行技术审核&#xff0c;以确保它符合搜索引擎的技术要求。研究关键词并确定目标关键词。优化网站内容&#xff0c;以便更好地针对目标关…

【LeetCode】剑指 Offer 55. 二叉树的深度 p271 -- Java Version

1. 题目介绍&#xff08;55. 二叉树的深度 &#xff09; 面试题55&#xff1a;二叉树的深度&#xff0c; 一共分为两小题&#xff1a; 题目一&#xff1a;二叉树的深度题目二&#xff1a;平衡二叉树 2. 题目1&#xff1a;二叉树的深度 题目链接&#xff1a;https://leetcode.c…

简单写一个Avue增删改查

今天练习了一下avue&#xff0c;真的好用&#xff0c;个人感觉相比于用element plus的组件还方便&#xff01; 简简单单的写了一个页面的增删改查&#xff0c;思路很简单。如果在写那种后台管理项目&#xff0c;基本上全是列表页&#xff0c;用这种方法写出来第一页&#xff0c…

收入下滑,亏损扩大的人力资源管理公司罗科仕申请纳斯达克IPO上市

来源&#xff1a;猛兽财经 作者&#xff1a;猛兽财经 猛兽财经获悉&#xff0c;来自北京的人力资源管理公司罗科仕近期已向美国证券交易委员会&#xff08;SEC&#xff09;提交招股书&#xff0c;申请在纳斯达克IPO上市&#xff0c;股票代码为(LGCL) 。罗科仕计划通过此次纳斯…

算法训练第五十八天 | 739. 每日温度、496.下一个更大元素 I

单调栈part01739. 每日温度题目描述思路496.下一个更大元素 I题目描述思路739. 每日温度 题目链接&#xff1a;739. 每日温度 参考&#xff1a;https://programmercarl.com/0739.%E6%AF%8F%E6%97%A5%E6%B8%A9%E5%BA%A6.html 题目描述 请根据每日 气温 列表&#xff0c;重新生…

Android组件化开发

Android组件开发 一、背景 一个app随着业务增加&#xff0c;代码放在同一个模块中会越来越臃肿&#xff0c;同时也导致多人开发的一个难度。组件化可以把业务单独分出来&#xff0c;形成一个单独模块&#xff0c;可单独运行、测试等&#xff0c;相互之间不会影响。另外一个优…

鼎捷T100制造之工艺工单实战(其他工艺补充)

文章目录 一、网状工艺二、平行工艺三、替代工艺四、返工工艺五、无顺序工艺一、网状工艺 网状工艺类似一张网状结构。可以包含平行和线性工艺等于一体。 网状工艺: 产品结构 aeci004:建立作业 aecm200: 工艺路线维护

kubeasz搭建k8s集群-部署单节点集群(AllinOne部署)

1说明 kubeasz 致力于提供快速部署高可用k8s集群的工具, 同时也努力成为k8s实践、使用的参考书&#xff1b;基于二进制方式部署和利用ansible-playbook实现自动化&#xff1b;既提供一键安装脚本, 也可以根据安装指南分步执行安装各个组件。 kubeasz 从每一个单独部件组装到完…

太赫兹高速通信系统前端关键技术

摘要&#xff1a;对构成太赫兹无线系统的2 种关键电路&#xff08;分谐波混频器和二倍频器&#xff09;进行了深入研究。在关键电路研究取得突破的基础上&#xff0c;开展了太赫兹无线通信技术研究&#xff0c;构建了220 GHz 无线通信实验验证系统。220 GHz 实验验证系统在室外…

elasticsearch 其他字段类型详解和范例

本章主要内容 elasticsearch 中别名字段的详解和范例elasticsearch 中二进制类型的详解和范例elasticsearch 中的嵌套类型的详解和范例elasticsearch 中的范围类型的详解和范例elasticsearch 中的排名类型的详解和范例elasticsearch 中的ip类型的详解和范例elasticsearch 中的…

【网络应用开发】实验3——Web组件重用与JavaBeans

目录 Web组件重用与JavaBeans预习报告 一、实验目的 二、实验原理 三、实验预习内容 1. 静态include指令何时执行&#xff1f;主页面和被包含的子页面是否转换为一个转换单元&#xff1f; 2.动作指令何时执行&#xff1f;主页面和被包含的子页面是否转换为一个转换单元&a…

【Python游戏】坦克大战、推箱子小游戏怎么玩?学会这些让你秒变高高手—那些童年的游戏还记得吗?(附Pygame合集源码)

前言 下一个青年节快到了&#xff0c;想小编我也是过不了几年节日了呢&#xff01;&#xff01; 社交媒体上流传着一张照片——按照国家规定“14岁到28岁今天都应该放半天假&#xff01;”不得不说&#xff0c; 这个跨度着实有点儿大&#xff0c;如果按整自然年来算年龄&…

Spark 连接 Hive

目录 导包 修改配置文件 修改hive-site.xml文件 启动hadoop 启动hive 启动spark 测试 查看表 导包 spark连接hive需要六个关键的jar包&#xff0c;以及将hive的配置文件hive-site.xml拷贝到spark的conf目录下。如果你hive配置没问题的话&#xff0c;这些jar都在hive的目…

Spring Security实战(四)—— 会话管理

目录 一、理解会话 二、防御会话固定攻击 三、会话过期 四、会话并发控制 五、集群会话的缺陷 六、集群会话的解决方案 七、整合Spring Session解决集群会话问题 只需在两个浏览器中用同一个账号登录就会发现&#xff0c;系统并没有任何会话并发限制。一个账号可以多处同…

cuSPARSE官方程序示例

cuSPARSE Library 简介 这个文件演示了cuSPARSE通用API的用法 官方程序&#xff1a;后续会出解析&#xff08;20230410&#xff09; cuSPARSE Generic APIs Documentation cuSPARSE Samples 向量 - 向量 操作矩阵 - 向量 操作矩阵 - 矩阵操作转换Legacy APIs优化稀疏迭代…