~/learn

Detect holes

The sample demonstrates how to detect data and hole segments in the given 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.