Skip to content

Instantly share code, notes, and snippets.

@DrPizza
Created April 27, 2017 07:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save DrPizza/f9f4e553d7d0fba19d9de0f2cc84c26a to your computer and use it in GitHub Desktop.
Save DrPizza/f9f4e553d7d0fba19d9de0f2cc84c26a to your computer and use it in GitHub Desktop.
#include <SDKDDKVer.h>
#pragma warning(disable: 4710) // warning C4710: '%s': function not inlined
#pragma warning(disable: 4668) // warning C4668: '%s' is not defined as a preprocessor macro, replacing with '0' for '#if/#elif'
#pragma warning(disable: 4820) // warning C4820: '%s': '%d' bytes padding added after data member '%s'
#define STRICT
#define NOMINMAX
#include <Windows.h>
#if !defined(_STL_EXTRA_DISABLED_WARNINGS)
#define _STL_EXTRA_DISABLED_WARNINGS 4061 4365 4571 4623 4625 4626 4710 4774 4820 4987 5026 5027
#endif
#include <vector>
#include <memory>
#include <iostream>
#include <locale>
#include <codecvt>
DWORD get_sector_size(const std::wstring& path) {
DWORD sectors_per_cluster = 0ul;
DWORD bytes_per_sector = 0ul;
DWORD free_clusters = 0ul;
DWORD total_clusters = 0ul;
::GetDiskFreeSpaceW(path.c_str(), &sectors_per_cluster, &bytes_per_sector, &free_clusters, &total_clusters);
return bytes_per_sector;
}
unsigned __int64 align_down(unsigned __int64 value, unsigned __int64 alignment) {
if(alignment == 0 || 0 != (alignment & (alignment - 1))) {
return value;
}
return value & ~(alignment - 1ui64);
}
template<typename T>
T greatest_common_divisor(T a, T b) {
if(a == 0) {
return b;
}
if(b == 0) {
return a;
}
T shift = 0;
for(; 0 == ((a | b) & 1); ++shift) {
a >>= 1;
b >>= 1;
}
while(0 == (a & 1)) {
a >>= 1;
}
do {
while(0 == (b & 1)) {
b >>= 1;
}
if(a > b) {
std::swap(a, b);
}
b -= a;
} while(b != 0);
return a << shift;
}
template<typename T>
T least_common_multiple(T a, T b) {
return (a * b) / greatest_common_divisor(a, b);
}
int main(int argc, char* argv[])
{
std::wstring drive = std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>>{}.from_bytes(argc == 2 ? argv[1] : "C:\\");
ULARGE_INTEGER free_bytes = { 0 };
::GetDiskFreeSpaceExW(drive.c_str(), &free_bytes, nullptr, nullptr);
std::wstring path = drive + L"space_filler";
HANDLE space_filler = ::CreateFileW(path.c_str(), GENERIC_ALL, 0, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_NO_BUFFERING | FILE_FLAG_DELETE_ON_CLOSE, nullptr);
DWORD sector_size = get_sector_size(drive);
constexpr size_t buffer_size = 1024 * 1024;
free_bytes.QuadPart = align_down(free_bytes.QuadPart, least_common_multiple(static_cast<size_t>(sector_size), buffer_size));
LARGE_INTEGER distance = { 0 };
distance.QuadPart = static_cast<__int64>(free_bytes.QuadPart);
::SetFilePointerEx(space_filler, distance, nullptr, FILE_BEGIN);
::SetEndOfFile(space_filler);
LARGE_INTEGER zero = { 0 };
::SetFilePointerEx(space_filler, zero, nullptr, FILE_BEGIN);
std::unique_ptr<unsigned char[]> even_buffer{ new unsigned char[buffer_size] };
std::unique_ptr<unsigned char[]> odd_buffer{ new unsigned char[buffer_size] };
for(size_t i = 0; i < buffer_size; ++i) {
even_buffer[i] = static_cast<unsigned char>( i & 0xff );
odd_buffer [i] = static_cast<unsigned char>(~(i & 0xff));
}
std::unique_ptr<unsigned char[]> read_buffer{ new unsigned char[buffer_size] };
const size_t blocks_to_write = free_bytes.QuadPart / buffer_size;
for(size_t iterations = 0; ; ++iterations) {
unsigned char* buffer = (iterations % 2) ? odd_buffer.get() : even_buffer.get();
for(size_t i = 0; i < blocks_to_write; ++i) {
DWORD bytes_written = 0ul;
::WriteFile(space_filler, buffer, buffer_size, &bytes_written, nullptr);
}
::SetFilePointerEx(space_filler, zero, nullptr, FILE_BEGIN);
for(size_t i = 0; i < blocks_to_write; ++i) {
DWORD bytes_read = 0ul;
::ReadFile(space_filler, read_buffer.get(), buffer_size, &bytes_read, nullptr);
if(0 != std::memcmp(read_buffer.get(), buffer, buffer_size)) {
std::cout << "read error detected" << std::endl;
}
}
::SetFilePointerEx(space_filler, zero, nullptr, FILE_BEGIN);
std::cout << "Written " << (iterations + 1) * (blocks_to_write * buffer_size) << std::endl;
}
::CloseHandle(space_filler);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment