Converting multipath devices to its equivalent physical disk - c++

In linux/unix I want to get the physical disk name given the multipathed device name.
For Eg: if the multipath device name is /dev/mpath/mpath0 where mpath0 is the multipathed device and is mapped to say disk /dev/sdc. Here when I input mpath0 I want sdc as the output.
When you do a 'multipath -ll' you get a list of multipathed devices and its corresponding physical disks but if the list is too large its difficult to parse and get the right information. Is there a way to do this programmatically in C or C++ ?
Thanks

Related

How to get disk information on Linux?

The purpose is to obtain information about the physical hard disk under the Linux platform. The required information includes the physical hard drive name (caption), device path (such as /dev/sda), read/write rate and read and write throughput of each physical disk, total disk capacity and remaining available capacity per physical disk. I eventually need to get this information in the program in C++. But I also accept the command line acquisition method.
I have tried lshw, smartctl, hdparm, lsblk, fdisk.etc, but some of these commands are not available on different Linux distributions. And these methods can't get all the information I want. I also tried to get information from /proc/diskstats, /sys/block, etc., but it didn't solve the problem. The confusion between logical disks and physical disks also makes processing difficult. It is important to emphasize that the information you need to obtain is for each physical disk.
fdisk -l command will show you in details.

Access the RAW disk using 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.

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

Device unique ID (hardware serial ID vs volume serial ID) Windows

I've been messing around with the Windows API (I've been told to stay away from WMI as it's unreliable), trying to get device serial numbers for my HDs and attached USB devices. But it seems that the majority of the functionality is designed to access Volume Serial IDs and not the actual manufacturer's unique serial number of the device. These Volume Serials seem to be calculated based on the last date and time the drive was formatted.
Well, this won't do for the application I want to develop - if a device is formatted and the same info copied to that device, then when they start my application, it needs to be able to treat the internal info (identified via the serial number) as belonging to that device, which if I use the Volume Serial ID will be lost.
I looked at the code for http://www.winsim.com/diskid32/ but that seems to just return the volume serial ID. EDIT: Actually, this value is different to the volume serial, as you can see in the below output:
Vol Name is Hellblazer
Vol Serial is 3358611714
Max Filelength is 255 chars
Filesystem is NTFS
202020202020202020205a204339464a38305345
Z9CJF08ES
The serial in the first bit of code (using GetVolumeInformation) is the decimal version of the hexidecimal value you get for the drive when typing 'vol' in the command prompt - so this is the Volume serial. The below number is what gets returned from DeviceIoControl(hwDrive, IOCTL_STORAGE_QUERY_PROPERTY.... It's the same ID the programmer of diskid32 gets for my drive, yet different to the actual serial below. Perplexing.
For USB drives:
Using a PSP_DEVICE_INTERFACE_DETAIL_DATA struct, I can get access to the GUID device enumeration, which looks like this for my USB drive:
\?\usbstor#disk&ven_toshiba&prod_mk5059gsxp&rev_gn00#203216187542__&0#{53f563
07-b6bf-11d0-94f2-00a0c91efb8b}
This part of that device information is the serial, supposedly:
203216187542__
Additionally, I loaded up diskpart.exe (a cmd line partition program) and had a look at the drive details of my system HDD and an external USB drive and neither of them matched any of the values I'm getting above:
TOSHIBA MK5055GSXF ATA Device Disk ID: 00005B9E
TOSHIBA MK5059GSXP USB Device Disk ID: 51260D08
What could be going on here? Where, and how can I gain access to the actual manufacture serial number of the actual device?
Any help would be greatly appreciated!

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 :-)