有一个功能设置"有效数据长度"价值:SetFileValidData
,但我找不到获取"有效数据长度的方法"值。
如果EOF与VDL不同,我想知道给定的文件,因为在VDL<EOF
的情况下在VDL之后写入将导致性能损失,如here所述。
答案 0 :(得分:1)
我认为你对什么&#34;有效数据长度&#34;感到困惑。实际上意味着。检查this answer。
基本上,虽然SetEndOfFile
允许您快速增加文件的长度,并分配磁盘空间,但如果跳到(新)文件结尾写入,则所有额外分配的磁盘空间需要用零覆盖,这有点慢。
SetFileValidData
可让您跳过归零。你告诉系统,&#34;我对这些磁盘块中的任何内容都没关系,继续使用它&#34;。 (这就是为什么你需要SE_MANAGE_VOLUME_NAME
特权,因为如果你不覆盖数据,它可以向非特权用户显示特权数据。 这个特权的用户可以访问原始驱动器无论如何数据。)
在任何一种情况下,您都设置了文件的新有效大小。 (你可以回读。)确切地说,应该一个单独的&#34;读取文件有效数据&#34;报告回来? SetFileValidData
告诉系统这些磁盘块中的任何内容 &#34;有效&#34; ...
不同的解释方法:
documentation提到&#34;有效数据长度&#34;正在跟踪 ;这样做的目的是让系统在{{1}的上下文中知道它仍然需要归零的范围(从有效结束数据到结束文件)。必要时(例如关闭文件)。 您不需要回读此值,因为它与实际文件 size 的唯一方式不同是因为您,你自己,确实通过上述功能改变了它......
答案 1 :(得分:0)
SetValidData
(根据MSDN)可用于创建例如大文件而无需写入文件。对于数据库,这将分配一个(连续的)存储区域。
结果,似乎磁盘上的文件大小已经改变,而没有任何数据写入文件。
通过暗示,任何GetValidData
(不存在)只返回文件的大小,因此您可以使用GetFileSize
返回“有效”文件大小。
答案 2 :(得分:0)
我找到了this页面,声称:
没有机制来查询VDL的值
所以答案是“你不能”。
如果您关心性能,可以将VDL设置为EOF,但请注意,您可以允许访问磁盘上的旧垃圾 - 这两个指针之间的部分,如果您不访问该文件则应该为零将VDL设置为指向EOF。
答案 3 :(得分:0)
对此进行了调查。无法通过任何API获取此信息,即使是NtQueryInformationFile API(FileEndOfFileInformation仅与NtSetInformationFile一起使用)。所以最后我通过手动读取NTFS记录来阅读此内容。如果有人有更好的方法,请告诉!显然,这也仅适用于完全系统访问(和NTFS),并且可能与Windows使用的内存中信息不同步。
#pragma pack(push)
#pragma pack(1)
struct NTFSFileRecord
{
char magic[4];
unsigned short sequence_offset;
unsigned short sequence_size;
uint64 lsn;
unsigned short squence_number;
unsigned short hardlink_count;
unsigned short attribute_offset;
unsigned short flags;
unsigned int real_size;
unsigned int allocated_size;
uint64 base_record;
unsigned short next_id;
//char padding[470];
};
struct MFTAttribute
{
unsigned int type;
unsigned int length;
unsigned char nonresident;
unsigned char name_lenght;
unsigned short name_offset;
unsigned short flags;
unsigned short attribute_id;
unsigned int attribute_length;
unsigned short attribute_offset;
unsigned char indexed_flag;
unsigned char padding1;
//char padding2[488];
};
struct MFTAttributeNonResident
{
unsigned int type;
unsigned int lenght;
unsigned char nonresident;
unsigned char name_length;
unsigned short name_offset;
unsigned short flags;
unsigned short attribute_id;
uint64 starting_vnc;
uint64 last_vnc;
unsigned short run_offset;
unsigned short compression_size;
unsigned int padding;
uint64 allocated_size;
uint64 real_size;
uint64 initial_size;
};
#pragma pack(pop)
HANDLE GetVolumeData(const std::wstring& volfn, NTFS_VOLUME_DATA_BUFFER& vol_data)
{
HANDLE vol = CreateFileW(volfn.c_str(), GENERIC_WRITE | GENERIC_READ,
FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (vol == INVALID_HANDLE_VALUE)
return vol;
DWORD ret_bytes;
BOOL b = DeviceIoControl(vol, FSCTL_GET_NTFS_VOLUME_DATA,
NULL, 0, &vol_data, sizeof(vol_data), &ret_bytes, NULL);
if (!b)
{
CloseHandle(vol);
return INVALID_HANDLE_VALUE;
}
return vol;
}
int64 GetFileValidData(HANDLE file, HANDLE vol, const NTFS_VOLUME_DATA_BUFFER& vol_data)
{
BY_HANDLE_FILE_INFORMATION hfi;
BOOL b = GetFileInformationByHandle(file, &hfi);
if (!b)
return -1;
NTFS_FILE_RECORD_INPUT_BUFFER record_in;
record_in.FileReferenceNumber.HighPart = hfi.nFileIndexHigh;
record_in.FileReferenceNumber.LowPart = hfi.nFileIndexLow;
std::vector<BYTE> buf;
buf.resize(sizeof(NTFS_FILE_RECORD_OUTPUT_BUFFER) + vol_data.BytesPerFileRecordSegment - 1);
NTFS_FILE_RECORD_OUTPUT_BUFFER* record_out = reinterpret_cast<NTFS_FILE_RECORD_OUTPUT_BUFFER*>(buf.data());
DWORD bout;
b = DeviceIoControl(vol, FSCTL_GET_NTFS_FILE_RECORD, &record_in,
sizeof(record_in), record_out, 4096, &bout, NULL);
if (!b)
return -1;
NTFSFileRecord* record = reinterpret_cast<NTFSFileRecord*>(record_out->FileRecordBuffer);
unsigned int currpos = record->attribute_offset;
MFTAttribute* attr = nullptr;
while ( (attr==nullptr ||
attr->type != 0xFFFFFFFF )
&& record_out->FileRecordBuffer + currpos +sizeof(MFTAttribute)<buf.data() + bout)
{
attr = reinterpret_cast<MFTAttribute*>(record_out->FileRecordBuffer + currpos);
if (attr->type == 0x80
&& record_out->FileRecordBuffer + currpos + attr->attribute_offset+sizeof(MFTAttributeNonResident)
< buf.data()+ bout)
{
if (attr->nonresident == 0)
return -1;
MFTAttributeNonResident* dataattr = reinterpret_cast<MFTAttributeNonResident*>(record_out->FileRecordBuffer
+ currpos + attr->attribute_offset);
return dataattr->initial_size;
}
currpos += attr->length;
}
return -1;
}
[...]
NTFS_VOLUME_DATA_BUFFER vol_data;
HANDLE vol = GetVolumeData(L"\\??\\D:", vol_data);
if (vol != INVALID_HANDLE_VALUE)
{
int64 vdl = GetFileValidData(alloc_test->getOsHandle(), vol, vol_data);
if(vdl>=0) { [...] }
[...]
}
[...]