Windows physical drive access fopen and fseek

2020-04-19 05:29发布

问题:

I'm currently trying to access a physical hard disk as a stream of binary data in C. I've mounted an image (.img), and it's readable from the OS (Win 7).

My C program simply attempts to open the physical drive in read-only binary mode, then read some data from the drive.

However, if I simply read data from the stream without seeking anywhere, all is well, I get back the data that is stored in the drive, and as I'm at offset 0 in the stream, I'm able to read the MBR on the disk.

However, if I try to fseek to any offset from the origin (zero), fseek return -1, indicating that it couldn't do it.

I'm guessing this might be a permission/ring 3/user level problem with accessing physical disks, and I'm probably going to have to write a driver to get kernel level access to do this, I'm just confused why I can read some data fine from the first sector, but I can't seek to any other offsets. I've included part of the C program I've written below.

FILE *disk = fopen("\\\\.\\PhysicalDrive1, "rb+");
if (disk == NULL) {
    **error handle
 }
else { //Opened the drive sucessfully
fread(buffer, 1, 100, disk);
printf("Reading the first byte from buffer, it's:%d\n", buffer[0]);
//This works fine and I can read any byte within the initial buffer
int test = fseek(disk, 100, SEEK_SET);
printf("The value of fseek is:%d\n", test);
//This always returns -1, indicating the seek failed  
fclose(disk);
}

回答1:

Quote from msdn:

If successful, fseek returns 0. Otherwise, it returns a nonzero value. On devices incapable of seeking, the return value is undefined. If stream is a null pointer, or if origin is not one of allowed values described below, fseek invoke the invalid parameter handler, as described in Parameter Validation. If execution is allowed to continue, these functions set errno to EINVAL and return -1.

Section 7.21.9.2 of the C standard [ISO/IEC 9899:2011] specifies the following behavior for fseek() when opening a binary file in binary mode:

A binary stream need not meaningfully support fseek calls with a whence value of SEEK_END.

In addition, footnote 268 of Section 7.21.3 has this to say:

Setting the file position indicator to end-of-file, as with fseek(file, 0, SEEK_END), has undefined behavior for a binary stream (because of possible trailing null characters) or for any stream with state-dependent encoding that does not assuredly end in the initial shift state.

A lot of low-level stuff matters, like sector alignment, file systems,etc. which needs a specific driver program to help navigating through the drives also need to be considered.

Hope this helps.