1

Basically, I am trying to create my own tool to quick format ext4 partitions.

As far as I understand, the idea behind it is to find and overwrite existing inodes with empty ext2_inode structures. I thought that I could do it by simply calculating the difference between sb.s_inodes_count and sb.s_free_inodes_count so I would know how many inodes I have to overwrite.

But actually it doesn't work (just fails to mount after all) and I am curious why. If so, then how do I find correct inode location (if I found it incorrectly) and what do I do to write empty structures properly?

#include <iostream>
#include <ext2fs/ext2_fs.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include "Disk.h"

using namespace std;

Disk::Disk(string path){
    try{
        this->fd = open(path.c_str(), O_RDWR);
        if(this->fd == -1) throw new CantOpenDevice;
    } catch (CantOpenDevice& openError){
        logger->error(openError.what());
    }
}

ext2_super_block Disk::readSuperBlock(){
    lseek(this->fd, 1024, SEEK_SET); // 1024 - Group 0 Padding 
    read(this->fd, &this->sb, sizeof(ext2_super_block));
    this->logger->debug("Succesfully read superblock.");
    return this->sb;
}

ext4_group_desc Disk::readFirstBGD(){
    int block_size_offset = this->getBlockSizeOffset();
    lseek(this->fd, block_size_offset, SEEK_SET);
    read(this->fd, &this->bg, sizeof(ext4_group_desc));
    this->logger->debug("Succesfully read a group descriptor.");
    return this->bg;
}

void Disk::writeEmptyInodes(){
    ext2_inode inode = {0};
    int block_size_offset = this->getBlockSizeOffset();
    int inodes_to_clean = this->sb.s_inodes_count - this->sb.s_free_inodes_count;
    for(int i=1; i < inodes_to_clean; i++){
        write(this->fd, &inode, sizeof(inode));
    }
}

int Disk::getBlockSizeOffset(){
    return 1024 << this->sb.s_log_block_size;
}

Disk::~Disk(){
    close(this->fd);
    delete logger;
}
fpmurphy
  • 2,464
  • 1
  • 18
  • 22
teveve
  • 31
  • 5
  • Sidenotes: Why do you `throw new CantOpenDevice` only to try to catch and log it on the next line? Also, don't do `new` when you `throw`. You now throw a _pointer_ to a `CantOpenDevice` (that you don't `delete`), not a `CantOpenDevice`. Why not simply do `if(this->fd == -1) logger->error("message");`? Another thing: You should encapsulate `fd` and `logger` to manage their own resources so that you don't have to implement a destructor in the `Disk` class. – Ted Lyngmo May 05 '20 at 16:09
  • 1
    Well, formatting is not that simple. You may also need to update the `Group Descriptor Table`, clear the `Inode Bitmap Blocks`, take care of flexible blocks (if it is enabled in ext4), and so on. In other words, it is much more complex than simply emptying the inodes from `inode table`. – campescassiano May 06 '20 at 03:00
  • @campescassiano uhh, yes, totally forgot about other data entries referencing inodes. – teveve May 06 '20 at 18:13

0 Answers0