New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot write to Windows device #1

Open
jviotti opened this Issue Dec 8, 2014 · 20 comments

Comments

4 participants
@jviotti

jviotti commented Dec 8, 2014

I'm using the library to correctly override the MBR of an sd card on OS X, however I'm having trouble doing the same on Windows 8, as even when write returns the correct bytes written, the changes are not reflected on the disk.

var device = new BlockDevice({
  path: '\\\\.\\PhysicalDrive1',
  mode: 'w+',
  size: 512
});

device.write(0, myNewMBRBuffer, callback);

Did you try this yourself? I appreciate if you can give me any clues if you encountered the same issue.

@jhermsmeier

This comment has been minimized.

Owner

jhermsmeier commented Dec 9, 2014

I did in fact encounter the same issue, but didn't get around to testing it extensively yet.
I was running Windows 10 Tech Preview and noticed that it wouldn't write to a device, even when run as admin - and I have absolutely no clue why that is, yet. It was working last year in December though (I was giving a talk about that stuff, and the demo was on Win 8).

My guess so far is that there has been some User Account Control or Security update which now prevents this. Will have a closer look at it now.

@jviotti

This comment has been minimized.

jviotti commented Dec 10, 2014

Thanks @jhermsmeier. I was also unable to read from any device. I'll keep investigating as well.

@jviotti

This comment has been minimized.

jviotti commented Dec 10, 2014

Using dd for windows works btw.

@jhermsmeier

This comment has been minimized.

Owner

jhermsmeier commented Dec 10, 2014

It appears you're only ever allowed to write to sectors not used by any file system, even when your process is elevated. Which basically means, that you have to "lock" or "off-line" (unmount) a disk before a user-land process is allowed to write all over the device. (You can manually "offline" devices in the Disk Manager.)

See: Changes to the file system and to the storage stack to restrict direct disk access and direct volume access

Looks like I'll have to figure out how to lock a device or volume programmatically before writing

@jhermsmeier

This comment has been minimized.

Owner

jhermsmeier commented Dec 10, 2014

Also note (in case it's not just a typo), that you probably want to specify the blockSize instead of the size of the device (in your example) - size would mean that PhysicalDevice1 has only 512 bytes of storage:

var device = new BlockDevice({
  // ...
  blockSize: 512
});
@jviotti

This comment has been minimized.

jviotti commented Dec 10, 2014

@jhermsmeier Thanks for the information. As described in the first post, I'm trying to write to an SD card, but I'm unable to get it offline from Disk Management. See http://www.eightforums.com/general-support/16613-disk-management-how-bring-disk-offline.html:

Not all USB drives are recognized properly to do this.
If your USB disk is only recognized as a removable device and not as a drive, then you can't use it this way. You can create a VHD on it and attach the VHD to your VM, but you can't use it as a passthrough disk.

I'm unable to get it offline with and without the USB adapter.

About blockSize, it was indeed a typo when manually copying the example from my Windows laptop.

I'll try to borrow a W7 pc to test there.

Thanks for the great support!

@jviotti

This comment has been minimized.

jviotti commented Dec 10, 2014

I tried to unmount the disk with:

> mountvol X: /D

The corresponding letter was no longer visible from "My Computer", but I could see it from "Disk Management" or:

> wmic diskdrive list brief

I then tried to perform the write but no luck. The read operation didn't work neither.

@jhermsmeier

This comment has been minimized.

Owner

jhermsmeier commented Dec 10, 2014

Just remebered that the \\.\PhysicalDriveN only works for (things that act like) hard drives, not removable media. If something acts like a removable disk (or floppy, CD-ROM, etc.), \\.\X: opens the raw drive. This is due to the SD Card reader (for example) being the actual physical device, I believe. So it depends heavily on the device type.

I'll have to do some more experimenting on all of this - it would be really great if I can manage to get everything working with JS only, but in the worst case I'll have to resort to C/C++ bindings to make node-blockdevice work properly...

Thank you for the help & interest in this, very appreciated!

@jviotti

This comment has been minimized.

jviotti commented Dec 10, 2014

@jhermsmeier Attempting to open a device in the form of \\.\X: results in:

ENOENT, open 'C:\X:'

Maybe extra syntax is needed to make Nodejs interpret it as an absolute path (I'm really unfamiliar with Windows)?

Thanks a lot for the support, and hope we can get this working, and let me know if I can help with anything.

Also, It'd be nice if you can write a README for newcomers, explaining usage, caveats, etc, as I had to look into the source code in order to understand/use the module.

@jhermsmeier jhermsmeier added the bug label Dec 10, 2014

@jhermsmeier jhermsmeier added this to the 1.0.0 milestone Dec 10, 2014

@jviotti

This comment has been minimized.

jviotti commented Dec 10, 2014

I've tried the experiment in a Windows 7 PC. Exact same results.

@jviotti

This comment has been minimized.

jviotti commented Dec 10, 2014

\\.\X: fails like described above, but simply X: or X:\\ seems to work, however I get permissions errors even on admin cmd:

EPERM, open 'X:\'
@jhermsmeier

This comment has been minimized.

Owner

jhermsmeier commented Dec 13, 2014

Little update on my investigations of errors on Windows:
I've managed to get something different with a USB thumb drive, using:

// Note that using `r+` or `rs+` as mode
// won't result in file creation if it doesn't exist,
// since you were creating files in `C:\` on open
var device = new BlockDevice({
  path: '\\\\.\\F:',
  mode: 'rs+',
})

Reading works just fine, no success writing to it though; now I get an E_INVAL, errno 18 (Invalid cross-device link). With path: '\\\\.\\PhysicalDevice2' I get an E_PERM, errno 50, where errno 50 should actually correspond to E_NOCSI No CSI structure available. / Links between structures are invalid..

I currently still don't know what exactly those errors are supposed to tell me, but Windows is making it quite difficult to get raw write access to a block device these days.

@jviotti

This comment has been minimized.

jviotti commented Dec 16, 2014

@jhermsmeier Thanks for the update. I'll test this out on my SDCard and will let you know how it goes.

@jviotti

This comment has been minimized.

jviotti commented Dec 16, 2014

@jhermsmeier I've gave it a try on my SD card. I can effectively read from the device without any errors not permissions issues (tried reading the first 512 bytes).

I've compared that to a MBR dump from the SD card that I generated on OS X, but the data differs.

By taking a look at the data, it doesn't seems to be reading correctly:

�X�MSDOS5.0�
�?�����:�)?�xNO NAME    FAT32   3ɎѼ�{��ٽ|�V@�N�V@�A��U�r��U�u
��t�F�-�V@�s�����f��@f������Af��f��f�F�~u9�~*w3f�Ff��
                                                        ����,���}��|���t<�t   ������}��}��ߘ��f`�~� fjfPSfh�B�V@���fXfXfXfX�3f;F�r��*f3�f�Nf�����f��f���v�֊V@����
 ̸�fa�t���f@Iu��BOOTMGR
Disk error�
Press any key to restart
��U�%

In the middle of the gliberish I can see:

MSDOS5.0
NO NAME    FAT32
BOOTMGR
Disk error
Press any key to restart

Do you get a similar output?

@jhermsmeier

This comment has been minimized.

Owner

jhermsmeier commented Jul 15, 2016

Hey, sorry I never answered this – I guess you've figured it out some time in the past two years already.

The gibberish with the MSDOS5.0 looks like a FAT Volume Boot Record to me – in this case probably the first sector of the FAT32 partition on the SD card, which is indeed not the wanted block.

I'm getting back to work on this module, and will do some fiddeling on Windows again soon, checking if and what changed about behavior and possibilities.

@jviotti

This comment has been minimized.

jviotti commented Jul 15, 2016

Hi @jhermsmeier ,

No worries! We indeed discovered and fixed the issue. Turns out that Windows policies for raw I/O to physical drives tells us that we can write to the drive without errors only in the following cases (this was linked by you in one of the first comments):

  • The sector we're trying to write to is the first sector of the drive.
  • The drive has no file system.

We're using diskpart.exe clean command to erase the file system from the drive before writing to it, and it works great.

All this work resulted in Etcher (http://www.etcher.io) and open source image writer based on Electron.

@lurch

This comment has been minimized.

Contributor

lurch commented Jan 11, 2017

@jorangreef

This comment has been minimized.

jorangreef commented Oct 24, 2017

@jviotti I've opened an issue in libuv to sort this out by exposing a UV_FS_O_EXLOCK flag, which will lock the block device for exclusive access to allow writing:

libuv/libuv#1605

@lurch

This comment has been minimized.

Contributor

lurch commented Oct 24, 2017

@jhermsmeier Did you ever get round to trying out the Etcher software that @jviotti mentioned? 😆

@jhermsmeier

This comment has been minimized.

Owner

jhermsmeier commented Oct 24, 2017

@lurch who? me? noooooooo...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment