Question

How can I write to any block on my HDD using the C programming language?

There was a question about writing the MBR but it didn't cover the C aspects that much.

Since filedescriptors are - as the word says - for files, I guess there is no way to use them in this case. The Low-level I/O included in the C standard library is also implemented with filedescriptors.

To put it more precisely:
This question is rather about writing HDD blocks than files (OS independent).

The answers to the question mentioned above basically suggested using dd (coreutils) on UNIX-Systems. This is why I am asking for a way in C. Maybe bootloaders (GRUB) and boot sector viruses use different techniques?

I guess changing the actual pointer inside of a filedescriptor is not a legitimate way.

Problems and limitations:
I know that there are certain aspects to keep in mind, such as

  • Some operating systems restrict direct access to volumes (e.g. Windows)
  • Writing errors as well as writing the wrong data into certain blocks might result in filesystem corruption (loss of data on the HDD).
  • Antivirus-Software might flag it as suspicious code.

This question is oriented more theoretical.

Was it helpful?

Solution

The C language has access to files with functions fopen/fclose/fread/fwrite etc. But there is no such thing as a block device in the language (not even a device, for that matter).

POSIX on the other hand has the low level functions open/close/read/write to access to files, and have the concept of block device. These functions can be used (with care) for a block device, as long as you follow a few simple rules (block alignment, mainly) and you know the name of your device (/dev/xxx).

If you are in a non-POSIX system, such as Windows, then the OS will have a specific way to handle the block device access. In Windows, for example, you can use the CreateFile function with the device name \\.\PhysicalDrive0, \\.\C: or such.

OTHER TIPS

For Unix-like operating systems, this is a non-question: The hard disk is a device file just like any other, and accessed just like any other file. You get a file descriptor, you seek, you write, you crash the filesystem, and all is good.

This implies that you should use the normal file I/O routines in C, too. Distinguishing between high-level and low-level I/O is not your job, but the operating system's. Because most operating systems nowadays support the device-as-file metaphor, there is no further abstraction in C. While this approach might not work for DOS and derivatives, this is only a reason to avoid DOS to avoid maintaining obsolete code.

If you want to make it OS independent then you probably want into using some kind of polymorphism. You then can create a structure to support your required functionality.

Where you create a structure that would then contain functions to pointers which can be changed when the code moves OS. You would then need a OS based implementation for each OS you want to support.

This has little to nothing to do with C. How one programmatically accesses a piece of hardware depends on how the CPU can communicate with that device (i.e. on the system/hardware architecture/design) and, if there's any OS involved, on how the OS lets other software running in it access the device (if at all).

On the x86 PC, if there's no OS running, you can use BIOS interrupt 13h functions to read and write HDD sectors. It's possible to use well-known I/O ports and ATA(PI) commands to achieve the same without using the BIOS. If there's DOS, it's about the same, there's no restriction on hardware accesses. If there's Windows or Linux, the OS won't let you do this kind of things unless you have sufficient privileges and/or do things in a certain way.

open() close() read() write() are not part of the C language, they are part of the OS.

Besides: write() doen not write anything, it is a systemcall asking the OS to write it for you. The OS can do anything it wants with this request (such as ignore it)

The /dev/* entries are just a hook into the machine's private parts, given to you by the OS to enable you do things that cannot be done otherwise. But when you open() and write() one of the /dev/disk devices, the OS still has the power to ignore your request.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top