今天寫個程式要在NTFS file system上產生 Sparse File.
參考MSDN #1 上面的說法, 要使用 FSCTL_SET_SPARSE 和 FSCTL_SET_ZERO_DATA 來產生 Sparse File.
不過照上面說的卻不work.
Google 了一下, 才找到#2這個網頁,
裡面明確說到, 如果你所填的zero bytes是在檔尾,
就需要用 SetFilePointer 和 SetEndOfFile 來讓資料真的寫入檔案.
後來發現事實上, 只需要用 FSCTL_SET_SPARSE,
然後再用SetFilePointer 和 SetEndOfFile 移到你想要的位置. 就可以產生Sparse File.
反之, 如果空洞是在檔案中間, 就不需要 SetEndOfFile.
但還是需要 SetFilePointer, 然後再 WriteFile 就可以了.
Sample code 如下:
/******************************************/
#include <windows.h>
#include <stdio.h>
int main()
{
HANDLE hFile;
int rc;
DWORD BytesReturned;
BY_HANDLE_FILE_INFORMATION byHandleFile = { 0 };
FILE_ZERO_DATA_INFORMATION fileZeroData = { 0 };
LARGE_INTEGER sparse_size;
sparse_size.QuadPart = 0xf0000000;
hFile = CreateFile("t:\\test.log", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
printf("hFile = %p\n", hFile);
rc = DeviceIoControl(hFile, FSCTL_SET_SPARSE,
NULL, 0,
NULL, 0, &BytesReturned, 0);
printf(" DeviceIoControl(FSCTL_SET_SPARSE) rc = %d\n", rc);
rc = WriteFile(hFile, "123", 3, &BytesReturned, 0);
printf("WriteFile(123) rc = %d\n", rc);
rc = GetFileInformationByHandle(hFile, &byHandleFile);
printf("GetFileInformationByHandle rc = %d sparkse=%d\n", rc, byHandleFile.dwFileAttributes & FILE_ATTRIBUTE_SPARSE_FILE);
/* // 這部分可以不需要
fileZeroData.FileOffset.QuadPart = byHandleFile.nFileSizeLow;
fileZeroData.BeyondFinalZero.QuadPart = fileZeroData.FileOffset.QuadPart + sparse_size.QuadPart;
rc = DeviceIoControl(hFile, FSCTL_SET_ZERO_DATA,
&fileZeroData, sizeof(fileZeroData),
NULL, 0, &BytesReturned, 0);
printf("DeviceIoControl(FSCTL_SET_ZERO_DATA) rc = %d\n", rc);
*/
//rc = SetFilePointer(hFile, 0x80000000, 1, FILE_END);
//printf("SetFilePointer() rc = %d\n", rc);
{ // 因為 sparse_size 太大, 所以要用 SetFilePointerEx
LARGE_INTEGER offset;
offset.QuadPart = sparse_size.QuadPart;
rc = SetFilePointerEx(hFile, offset, NULL, FILE_END);
printf("SetFilePointerEx() rc = %d\n", rc);
}
rc = SetEndOfFile(hFile);
printf("SetEndOfFile() rc = %d\n", rc);
CloseHandle(hFile);
hFile = CreateFile("t:\\test.log", GENERIC_READ, FILE_SHARE_READ,
0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
{
LARGE_INTEGER size;
rc = GetFileSizeEx(hFile, &size);
printf("GetFileSize() rc = %d size=%I64x\n", rc, size.QuadPart);
}
CloseHandle(hFile);
return 0;
}
#2: NTFS Sparse Files For Programmers http://www.flexhex.com/docs/articles/sparse-files.phtml