Skip to content
System Programming
Detect holes

Detect holes in the file

The sample demonstrates how to detect data and hole segments in the given file.

#include <iostream>
#include <fcntl.h>
#include <unistd.h>
#include <cerrno>
#include <cstring>
#include <sstream>
#include <cmath>
#include <limits>
 
int main(int argc, char** argv){
 
    // missing file name argument
    if(argc == 1){
        std::cerr << "Missing filename argument" << std::endl;
        exit(1);
    }
 
    // the name of file to analyze
    const char* filename = argv[1];
 
    // open file for read only
    int file = open(filename, O_RDONLY);
 
    // something went wrong 
    if(file < 0){
        std::cerr << "Error while opening the file " << filename << ". " << strerror(errno) << std::endl;
        exit(errno);
    }
 
    // keep the last index
    int last = 0;
 
    // go over the file
    while(true){
 
        // try jumping to the next beginning of hole
        off_t data = lseek(file, last, SEEK_HOLE);
 
        // there was some data if we got to next hole
        if(data > 0){
            
            // report segment
            std::cout << "Data Area Detected from " << last << " to " <<  data << std::endl;
 
            // move pointer
            last = data;
        }
 
        // reached the end of file
        if(data == 0){
            break;
        }
 
        // something went wrong
        if(data < 0){
            std::cerr << "Something went wrong. " << strerror(errno) << std::endl;
            exit(errno);
        }
 
        // try find next data jumping over a hole
        off_t hole = lseek(file, last, SEEK_DATA);
 
        // reached the end no data to read
        if(hole == -1 && errno == ENXIO){
            break;
        }
 
        // something went wrong
        if(hole == -1){
            std::cerr << "Something went wrong. " << strerror(errno) << std::endl;
            exit(errno);
        }
 
        if(hole > 0){
            // report segment
            std::cout << "Hole Area Detected from " << last << " to " << hole << std::endl;
 
            // move pointer
            last = hole;
        }
    }
 
    // no longer need the file
    int closed = close(file);
 
    // close the program
    return closed < 0 ? errno : 0;
}

The file can be compiled and executed as follows:

g++ dethole.cpp -o dethole
./dethole file_with_holes

The program is supposed to print start and end indexes of all the data and hole segments if any.