Thealexbarney / LibHac

A library that reimplements parts of the Nintendo Switch OS
Other
387 stars 44 forks source link

[v2] Fix E_ACCESSDENIED error when renaming directory #277

Closed jamestiotio closed 1 year ago

jamestiotio commented 1 year ago

There are cases when file managers or file explorers are used to access and modify save data files in the save data directory. This may cause the save data directory to be locked if those applications do not properly release or close the directory handle. Thus, when calls to DirectorySaveDataFileSystem.DoCommit() are made, which would invoke LocalFileSystem.RenameDirInternal() in turn, .NET would keep throwing an IOException with an HResult error code of 0x80070005 (E_ACCESSDENIED), indicating an Access Denied error.

This commit fixes this issue by performing either of the following:

  1. On Windows, manually rename the source directory to the dest directory via the P/Invoke API in shobjidl_core.h, which should be used by Windows Explorer in theory.
  2. On other Unix-based operating systems, manually call the rename system call via the Mono framework to execute the renaming.

It seems that DirectoryInfo operations are known to be quite janky and sensitive to those directories being used by other processes on the machine. This proposed implementation is supposed to be equivalent to the previous implementation and it is tested to be working on Ryujinx. The operation remains atomic and hence, it should not leave the file system in an inconsistent state.

Signed-off-by: James Raphael Tiovalen jamestiotio@gmail.com

jamestiotio commented 1 year ago

Note that I am only able to verify that this implementation fixes the original issue on Windows. I am unable to reproduce the original issue on Linux, and thus, the choice of implementation under the Unix branch condition is somewhat arbitrary. The only verification on Linux that I have performed was simply to ensure that it properly compiles and that it has the same behavior as the previous implementation. Would appreciate further testing, especially by those who can consistently reproduce the original issue.

Hopefully, this fixes Ryujinx/Ryujinx#5024.

jamestiotio commented 1 year ago

Never mind, testing this implementation by running Ryujinx multiple times shows that this does not fix the issue. It would still intermittently show a "Folder In Use" pop-up dialog box indicating that the folder is open in another program. Will close this PR.

Thealexbarney commented 1 year ago

If you use something like Process Explorer, can you tell which files/directories are being held open? I'm suspecting it might be related to thumbnail indexing

jamestiotio commented 1 year ago

@Thealexbarney It's the 0 directory and the slot_0x directory. More details in my comment here.