Access the RAW disk using C/C++ - c++

I have a large storage device (flash memory) plugged onto my computer via the PCIe bus, I want to access such device directly, i.e., without any file system (e.g., NTFS or ext4) on it.
How can I do this using C/C++? (on both Windows 7 and Linux)
I am wondering if I can 1) open the device just as a file, and then read and write binary data to it, or 2) allocate the whole device using some function like malloc, then each byte on the device have an address so that I can access them based on the addresses.
I prefer the second way if it possible, but I don't know if the OS supports this since it seems the address space needs to be shared with the main memory.

According to Microsoft documentation:
On Windows you can open a physical drive using CreateFile using a path of the form
\\.\PhysicalDriveN
where N is the device number or a logical drive using a path of the form
\\.\X:
You will need to seek, read and write in multiples of the sector size which can be retrieved using DeviceIoControl() with IOCTL_DISK_GET_DRIVE_GEOMETRY.

On Linux each storage device ends up getting a device entry in /dev. The first storage device is typically /dev/sda, the second storage device, if one is present, is /dev/sdb. Note that an optical disk is a storage device, so a CD-ROM or a DVD-ROM drive, if one is present, would get a device node entry.
Some Linux distributions may use a different naming convention, but this is what it usually is. So, you'll need to figure out which device corresponds to your flash disk, and just open the /dev/sdX device, and simply read and write from it. Your reads and writes must be for even block (sector) sizes, and seeking the opened file governs which disk blocks/sectors the subsequent read or write will affect.
Generally, /dev/sdX will be owned by root, but there are usually some Linux distribution-specific ways to fiddle the userid that owns a particular device node.

Related

Retrieve physical address of file on disk

Using the Windows API, I'm trying to write a program to read data from a disk. I managed to get access to the content of the drive using CreateFile and I'm able to search through it. Let's say there are some files on that disk and I know their paths, but I'm actually interested in their physical location.
My question is:
Is it possible to retrieve the physical location or address of the files (or sector they're located in) and where are they stored on the drive without searching the whole drive? If so, what functions should I use? Using SetFilePointer or FindFirstFile don't seem to solve the solution either.
The whole point of any file system is to abstract the physical disk sectors and provide you a higher level abstraction (called files). So the answer to "Is it possible to retrieve the physical location" should be no! (in general); some code might even move the sectors of a file (e.g. a disk defragmenter and you could imagine it is running concurrently with your program, even if that is not recommended..)
For more, read wikipages on file systems and files, then read a good book such as Operating systems: Three Easy Pieces
Notice that by using files, you are expecting that your program behave similarly after having moved a file system into a different disk, provided the file paths, contents, and metadata remain the same. In particular, you could have two external USB disks enclosures with different geometries or capacities having the same file contents (perhaps even in different file systems, e.g. VFAT on one and NTFS on another), and you then expect your program to behave identically when accessing such files (in the first box or the second one). Whatever box is plugged, your program would (for example) access the same F:\MyDir\MyFile.dat file. As file systems, both boxes would appear identical. At the physical sector level, data would be organized very differently.
BTW, the physical organization of files inside a file system varies greatly from one file system to another one. You could use some Ext3 file system on your machine (since there are Ext3 drivers for Windows) - and that is actually useful to share some data between Linux & Windows on a dual boot PC -, and the file organization is different from a FAT one or a NTFS one.
You might get some way to query the kernel to get the actual physical sector location. But I am not sure it works for all file systems (what would be the meaning of a sector location for some remote NFS one). And that information could be stale before your program get it (e.g. if some defragmenter is working in parallel). Also, other processes could access and modify the same file system at the same time (so that meta data -e.g. the sector location- would be obsolete by the time your process is scheduled to run again).
On Windows and on Unix like systems, file system code runs in the kernel. And other processes could use that same code (and the same file system) while your process is not running. Both Windows and Unix have preemptive scheduling, so you have no guarantee that your process runs again in user mode before some other process is using the same file system.
Remember that in practice, your file data often stays in the page cache. And that is why you might not hear your disk working -if you still have a rotating hard disk- when accessing the same file several times in a row (e.g. running the same program on the same file twice, a few seconds apart; usually the second run is keeping the disk silent, because the file data is already in RAM).
In a comment you mention that you want
To watch the data of the file and for example see what happens to the data when it gets deleted or modified.
but that should work at the file system level. Linux has inotify(7) facilities for that (they work on most local file systems, e.g. Ext4 or BTRFS, but not on remote file systems à la nfs(5), and neither on pseudo file systems à la proc(5)). I don't know if Windows has something similar to Linux inotify (but probably yes, at least in some cases).
You probably should consider using some database (maybe as simple as sqlite), and perhaps you want ACID properties (then use some real RDBMS like PostGreSQL). With PostGreSQL you might use TRIGGERs to be aware that some data changed, even if some other program changes the same database.
You could also do some file locking, and adopt the convention that every program accessing your particular file should lock it appropriately.

USB drive WriteFile to sectors outside volume

I'm developing c++ WinAPI program to write data on my USB drive directly with CreateFile by the Volume{GUID} and WriteFile functions as dozens of examples do. As mentioned here in Remarks:
A write on a volume handle will succeed if the volume does not have a
mounted file system, or if one of the following conditions is true:
The sectors to be written to are boot sectors.
The sectors to be written to reside outside of file system space.
You have explicitly locked or dismounted the volume by using FSCTL_LOCK_VOLUME or FSCTL_DISMOUNT_VOLUME.
The volume has no actual file system. (In other words, it has a RAW file system mounted.)
I want write 100Mb of data on USB smoothly without any unmounting. So I've tried two of the cases from above.
The second case: writing outside of the file system (I've extended the number of sectors per partition without extending FAT32 table), but it doesn't work without unmounting!
The fourth case: write on the volume without any file system (unformatted). But it also doesn't work without unmounting!!!
Also I've tried to create the second partition (that is invisible for Windows) with/without file system and write directly there by the offset from the end of first partition, but also unsuccessfully: I can not read or write there.
So, if anybody knows ANSWER TO THE ONE OF THE QUESTIONS at least:
How can I create sectors inside the partition outside
the file system?
Is there an ability to write smoothly on USB directly?
Also can I write in Windows to the second partition on USB without
playing around with drivers, NTCreateFile and other deep functions?
I'm pretty sure it actually worked, but you don't realize that you're bypassing Windows. That means Windows will not have noticed what you did. So if you use Windows to check what you did, it will not report a change.
To address the individual sub-questions: A normal file system fills the entire partition, so you can't. Your functions write smoothly to USB, that's not the problem. And no, Windows normally treats USB as unpartitioned storage.

How do I find out what physical drive a file is on?

I would like to find out what physical media a file is on (either by filename or by handle).
I've read here that I can determine the physical drive of a given partition handle with a DeviceIoControl call.
But how do I get a partition handle from a filename? (Because NTFS allows to mount partitions in folders, I can't simply go by drive letter.)
The reason I'm asking is that copying a file to another physical drive is fastest when using asynchronous methods, but on the same drive it is fastest when done synchronously with a larger buffer. I want to write a function to determine the optimum copying algorithm for a given file and destination.
Volumes in Windows are generally mapped to drive letters (except on network shares).
You can create a volume file device handle on the source and destination using CreateFile() just passing in the drive letter path (ie: \\.\C:\). Use the returned handle with DeviceIoControl(). Compare the physical drives between the source and destination, and you should be good.
Discussion explained here: "To obtain the physical drive identifier for a volume, open ..."
http://msdn.microsoft.com/en-us/library/windows/desktop/aa363858%28v=vs.85%29.aspx

VC++ - How to get permission to write on NTFS boot sector?

I searched a lot to get write - access to the boot sector (Master File Table ). I used CreateFile function with write access parameters like, GENERIC_WRITE. Then used SetFilePointer and WriteFile to write on a particular memory address. But what I always get is System.AccessViolationException (Windows 7). Am I doing something wrong here ?
I want to know if there is any alternative to CreateFile - WriteFile functions to get wrtie - access to boot sector ?
OR I was thinking if there is any way to use Interrup Service Routine to write on particular disk sectors in VC++ (C++/Cli) ?
According to Microsoft KB you have to call CreateFile with FILE_SHARE_READ and FILE_SHARE_WRITE on "\\.\PhysicalDriveN", where N is zero-based physical drive index. Then you can access the entire drive as one huge file. You have to be an administrator on your machine for this to work!
You can open a physical or logical drive using the CreateFile()
application programming interface (API) with these device names
provided that you have the appropriate access rights to the drive
(that is, you must be an administrator). You must use both the
CreateFile() FILE_SHARE_READ and FILE_SHARE_WRITE flags to gain access
to the drive.
Once the logical or physical drive has been opened, you can then
perform direct I/O to the data on the entire drive. When performing
direct disk I/O, you must seek, read, and write in multiples of sector
sizes of the device and on sector boundaries. Call DeviceIoControl()
using IOCTL_DISK_GET_DRIVE_GEOMETRY to get the bytes per sector,
number of sectors, sectors per track, and so forth, so that you can
compute the size of the buffer that you will need.
Update: I did some research and I found out that starting Vista you have to obtain the lock on the volume or dismount it. Otherwise the writes would fail. In the docs Microsoft says:
If you write directly to a volume that has a mounted file system, you
must first obtain exclusive access to the volume. Otherwise, you risk
causing data corruption or system instability, because your
application's writes may conflict with other changes coming from the
file system and leave the contents of the volume in an inconsistent
state. To prevent these problems, the following changes have been made
in Windows Vista and later:
A write on a volume handle will succeed if the volume does not have a mounted file system, or if one of the following conditions is true:
The sectors to be written to are boot sectors.
The sectors to be written to reside outside of file system space.
You have explicitly locked or dismounted the volume by using FSCTL_LOCK_VOLUME or FSCTL_DISMOUNT_VOLUME.
The volume has no actual file system. (In other words, it has a RAW file system mounted.)
A write on a disk handle will succeed if one of the following conditions is true:
The sectors to be written to do not fall within a volume's extents.
The sectors to be written to fall within a mounted volume, but you have explicitly locked or dismounted the volume by using FSCTL_LOCK_VOLUME or FSCTL_DISMOUNT_VOLUME.
The sectors to be written to fall within a volume that has no mounted file system other than RAW.

Direct access to harddrive?

I was wondering how hard disk access works. Ex, how could I view/modify sectors? Im targeting Windows if that helps.
Thanks
This page seems to have some relevant information on the subject:
You can open a physical or logical
drive using the CreateFile()
application programming interface
(API) with these device names provided
that you have the appropriate access
rights to the drive (that is, you must
be an administrator). You must use
both the CreateFile() FILE_SHARE_READ
and FILE_SHARE_WRITE flags to gain
access to the drive.
Once the logical or physical drive has
been opened, you can then perform
direct I/O to the data on the entire
drive. When performing direct disk
I/O, you must seek, read, and write in
multiples of sector sizes of the
device and on sector boundaries. Call
DeviceIoControl() using
IOCTL_DISK_GET_DRIVE_GEOMETRY to get
the bytes per sector, number of
sectors, sectors per track, and so
forth, so that you can compute the
size of the buffer that you will need.
The documentation of CreateFile also offers some clues:
You can use the CreateFile function to open a physical disk drive or a volume,
which returns a direct access storage device (DASD) handle that can be
used with the DeviceIoControl function. This enables you to access the
disk or volume directly, for example such disk metadata as the partition
table. However, this type of access also exposes the disk drive or
volume to potential data loss, because an incorrect write to a disk
using this mechanism could make its contents inaccessible to the
operating system. To ensure data integrity, be sure to become
familiar with DeviceIoControl and how other APIs behave
differently with a direct access handle as opposed to a file system handle.
You can open a logical volume (e.g. c: drive) or a physical drive using win32's CreateFile() function. With the returned handle you can read and write sectors as needed.
This page at MSDN should get you started: CreateFile Function
I take no responsibility for damaged caused :-)