Skip to content

Fix failed to delete a readonly file on Windows file systems#3542

Merged
katzyn merged 1 commit intoh2database:masterfrom
J1031:bugfix/windows-file-delete
Jun 14, 2022
Merged

Fix failed to delete a readonly file on Windows file systems#3542
katzyn merged 1 commit intoh2database:masterfrom
J1031:bugfix/windows-file-delete

Conversation

@J1031
Copy link

@J1031 J1031 commented Jun 13, 2022

On Windows file systems, delete a readonly file can cause AccessDeniedException, we should change readonly attribute to false and then delete file

@katzyn
Copy link
Contributor

katzyn commented Jun 14, 2022

Thank you for your contribution!

What is your use case for this operation? Why you need to delete a protected file with H2?

@J1031
Copy link
Author

J1031 commented Jun 14, 2022

I just run test org.h2.test.store.TestMVStore on Windows, and it failed with exception AccessDeniedException

@J1031
Copy link
Author

J1031 commented Jun 14, 2022

And Exception stack is shown as follows

Exception in thread "main" org.h2.message.DbException: Cannot delete file "./data/test/TestMVStore" [90025-219] at org.h2.message.DbException.get(DbException.java:212) at org.h2.store.fs.disk.FilePathDisk.delete(FilePathDisk.java:209) at org.h2.store.fs.FileUtils.delete(FileUtils.java:109) at org.h2.test.store.TestMVStore.testCompactFully(TestMVStore.java:470) at org.h2.test.store.TestMVStore.test(TestMVStore.java:71) at org.h2.test.TestBase.testFromMain(TestBase.java:477) at org.h2.test.store.TestMVStore.main(TestMVStore.java:50) Caused by: org.h2.jdbc.JdbcSQLNonTransientException: Cannot delete file "./data/test/TestMVStore" [90025-219] at org.h2.message.DbException.getJdbcSQLException(DbException.java:554) at org.h2.message.DbException.getJdbcSQLException(DbException.java:477) ... 7 more Caused by: java.nio.file.AccessDeniedException: .\data\test\TestMVStore at sun.nio.fs.WindowsException.translateToIOException(WindowsException.java:83) at sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:97) at sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:102) at sun.nio.fs.WindowsFileSystemProvider.implDelete(WindowsFileSystemProvider.java:269) at sun.nio.fs.AbstractFileSystemProvider.deleteIfExists(AbstractFileSystemProvider.java:108) at java.nio.file.Files.deleteIfExists(Files.java:1165) at org.h2.store.fs.disk.FilePathDisk.delete(FilePathDisk.java:200) ... 5 more

@katzyn katzyn merged commit a08508a into h2database:master Jun 14, 2022
@J1031 J1031 deleted the bugfix/windows-file-delete branch June 14, 2022 21:32
@andreitokar
Copy link
Contributor

I do not think it's such a good idea. RO flag exist for a reason, and if user decide to remove file, there are tools to do so.
What if user has no permissions to remove file (unix), what if it is a directory, what if ...
On the other hand, test need to be fixed.

@J1031
Copy link
Author

J1031 commented Jun 15, 2022

I do not think it's such a good idea. RO flag exist for a reason, and if user decide to remove file, there are tools to do so. What if user has no permissions to remove file (unix), what if it is a directory, what if ... On the other hand, test need to be fixed.

So only delete file on Windows file systems with AccessDeniedException.

@katzyn
Copy link
Contributor

katzyn commented Jun 15, 2022

@andreitokar
Internal file system API of H2 is designed in that way:

/**
* Disable the ability to write. The file can still be deleted afterwards.
*
* @param fileName the file name
* @return true if the call was successful
*/
public static boolean setReadOnly(String fileName) {
return FilePath.get(fileName).setReadOnly();
}

And it doesn't provide any way to reset this flag back.

Actually I don't see how it can be reset on POSIX systems, we don't preserve original access permissions on them anywhere.

@katzyn
Copy link
Contributor

katzyn commented Jun 15, 2022

H2 can set RO flag only on Windows. This flag also prevents deletion on this system.

On POSIX systems H2 removes write permissions from owner, group and others instead (ACLs, if any, aren't touched). It doesn't prevent file deletion, H2 was always able to remove read-only files on them.

I think older versions of H2 were able to delete read-only files on Windows too, because legacy File.delete() calls removeFileOrDirectory() in WinNTFileSystem_md.c and it resets attributes back to normal before deletion, but I don't have a Windows system to test it.

New versions of H2 use NIO.2 API and this API throws an AccessDeniedException instead.

So this PR is expected to restore consistent behavior of old version of H2.

If we don't like it, we can add a new setWriteable() to FilePath and call in everywhere. But CI tests are run only on Linux, so unnoticed regressions are possible.

@andreitokar
Copy link
Contributor

H2 can set RO flag

If that's the case, and it was a regression, then I take it back, sorry for the noise.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants