51 options::single<size_t> defaultBlockSize(
'b',
"blockSize",
"block size to search in (o: take from filesystem)", 0);
53 preserveAtime.fRequire(&findZeroes);
54 defaultBlockSize.fRequire(&findZeroes);
55 auto remainingOptions = parser.fParse(argc, argv);
59 for (
const auto& file : remainingOptions) {
63 std::cout << file <<
" has " << statbuf.st_size <<
" bytes, " <<
64 statbuf.st_blocks <<
" blocks, i.e. " << statbuf.st_blocks * 512 <<
" bytes allocated, " <<
65 (statbuf.st_blocks * 512.) /
static_cast<double>(statbuf.st_size) <<
" fill factor\n";
67 auto blockSize = statbuf.st_blksize;
68 if (defaultBlockSize != 0) {
69 blockSize = defaultBlockSize;
72 void* blkBuf =
nullptr;
75 PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE,
77 "mmap block buffer with ", blockSize,
" bytes");
81 std::vector<std::pair<int, std::string>> what({{SEEK_HOLE,
"data"}, {SEEK_DATA,
"hole"}});
82 for (decltype(statbuf.st_size) pos = 0, toggle = 1, region = 0;
83 pos < statbuf.st_size;
85 auto next = lseek(fd, pos, what.at(toggle).first);
86 if (next == -1 && errno == ENXIO) {
87 next = statbuf.st_size;
90 "seek ", file,
"for ", what.at(toggle).second,
91 ", from offset ", pos);
95 std::cout << std::setw(6) << region <<
": " << what.at(toggle).second <<
"\t";
98 if (findZeroes && what.at(toggle).first == SEEK_HOLE) {
99 size_t zeroBlocksStart = 0;
100 bool lastBlockWasData =
true;
101 for (
auto offset = pos; offset < next;) {
102 auto bytesRead = pread(fd, blkBuf, blockSize, offset);
103 if (
is_nul(blkBuf, blockSize)) {
104 if (lastBlockWasData) {
105 zeroBlocksStart = offset;
107 lastBlockWasData =
false;
109 if (!lastBlockWasData) {
110 std::cout <<
"\tzeroes\t";
114 lastBlockWasData =
true;
118 if (!lastBlockWasData) {
119 std::cout <<
"\tzeroes";
128 struct timespec times[2];
129 memcpy(×[0], &statbuf.st_atim,
sizeof(
struct timespec));
130 memcpy(×[1], &statbuf.st_mtim,
sizeof(
struct timespec));
131 throwcall::good0(futimens(fd, times),
"set tims stamps on ", file,
" to old values");
135 if (blkBuf !=
nullptr) {
136 throwcall::good0(munmap(blkBuf, blockSize),
"munmap block buffer with ", blockSize,
" bytes");