Linux: direct access to the hard-disk in C

11,549

Solution 1

To pile on with the cautions...

Don't forget that you have to cooperate with the existing driver stack's own thread safety provisions and internal caching. Many threads in the system can (and will) be writing to the disk all the time. To wipe a free sector, you have to know it to be free and stay free while you have your way with it. It would be bad if you wiped a sector that the file system had already decided to use, but hadn't flushed the evidence of that decision out to disk yet so you had no way to know it was in use. This could result in data loss which can result in outraged users.

If you can guarantee that the file system is currently not mounted then you can, in principle at least, open /dev/sda (probably not the specific one you want!) and parse the on-disk data structures to do anything you need to do. This is actually how utilities like fsck and mkfs are implemented.

The remaining big issue is that you have to stay in sync with every version of every file system you might encounter. At least you have the source code available for the file system itself for reference, but it will not be easy to just port it out of the kernel and into a user-mode application.

My advice would be to use the file system itself to get you the guarantees you need. Open large files and fill them with your wipe patterns. Fill the disk to capacity. Note that if this might have a serious impact on any running daemons that assume that some disk space is available, so it might still need to be done on a system with most daemons and such killed. If you are aiming for a secure wipe, you will still need to worry about actually flushing the written blocks to disk between passes because everything in the normal file system is going to try to optimize multiple writes of a single block.

Solution 2

You can just open the block device (for example, /dev/sda) and read the sectors manually. However, that won't tell tell you if it's empty or not directly. Being empty or not is a something defined at the filesystem abstraction level. File system data structures store that kind of data and you should have a deep understanding of the specific filesystem to do so from the raw blocks (without using any filesystem provided function).

Solution 3

In all likelyhood, you don't want to access the block device via /dev/sd* or /dev/hd* directly. As others stated, you'll have to understand the raw underlying filesystem, and this will be very difficult.

If you're writing an application that wants to treat bytes on disk as a big linear address space, then check out the mmap() system call. You can create a large, empty file on disk, and then use mmap() to map it into your process space. From there, you can use regular memory operations to read and write to the underlying large file. Note that writes are buffered, so guaranteeing consistency can be tricky.

The advantage of this approach is that even if the underlying file is fragmented, your access pattern(s) can consider it as a linear collection of bytes.

Solution 4

If you're wanting to wipe all the free space in a filesystem, you can fill the filesystem with one big file full of zeros, sync it to disk, and then delete it. That may not get absolutely everything, particularly if you are dealing with a logging filesystem or the like, but it will do most of it. If you're wanting to wipe the disk so an image compresses better, this is probably all you need to do. If you're wanting to clean the disk for security reasons... welcome to the world of kernel development, please step into the deep end, and remember to wear something flame resistant.

There is a utility called zerofree to zero out free blocks in ext filesystems, and is intended for VM images. Remember, this is not something you should do to a mounted fileystem. That page also has some old kernel patches that might prove an interesting starting point for doing this on live filesystems.

Solution 5

OH MY.

Your code would have to:

  1. Walk the partition table to see what partition that falls in.
  2. Determine what kind of filesystem it is.
  3. For each filesystem you support, provide such a routine to see if that byte is in use
  4. Check if the filesystem is mounted
  5. If it is, walk the kernel records to find out if there is something not yet written to disk.
  6. Oh, and if you're using EXT4 or REISER, you can't know the answer to the previous so you might as well give up.

If I were you I'd reconsider what you are trying to do.

EDIT: seeing his comment for what he's actually trying to do,

  • Accept a partition rather than a raw disk
  • Require dismounted
  • Call e3fsck to roll up the journal
  • Walk each inode, finding the last block and wiping any free space in that block (filesize should tell where the data ends in the block)
  • Walk the allocation bitmaps, find any unallocated blocks and wipe them
  • Now the tricky part, wipe the journal.
  • Good luck
  • Oh, and READ THE FILESYSTEM DOCUMENTATION
Share:
11,549
Dotdat
Author by

Dotdat

Updated on June 05, 2022

Comments

  • Dotdat
    Dotdat over 1 year

    How can I obtain a raw access to the HD and know if that location is used or is a free space? Just a piece of example, I can obtain a direct access simply with an open and a read on a disk device, the goal is knowing whether the, for example, 10.000 byte is used or not.

  • Dotdat
    Dotdat over 14 years
    well... I'm trying to do such a kind of program to wipe all the free space, a disk wiper. The first and disrty way I've thought to use is to walk all the disk long, check which parts are free and reset them.
  • Dotdat
    Dotdat over 14 years
    thank, it's a good solution if you don't care about performances. The best solution I've imagined, is to develoap a deamon and during the idle time perform a random walk into the disk and "wipe around". It's not so easy but quite interesting....
  • RBerteig
    RBerteig over 14 years
    It will get real exciting when that randomly steps on a sector that is in use for something critical, such as the kernel ;-)