Remove absolute file path from FS errors

When dealing with invalid paths (for instance, ones which are too long
or malformed), Java may throw a FileSystemException. This contains the
absolute path (i.e. C:/Users/Moi/.../.minecraft/...), which is printed
to the user within CC - obviously not ideal!

We simply catch this exception within the MountWrapper and map it back
to the local path. The disadvantage of doing it here is that we can't
map the path in the exception back to the computer - we'd need to catch
it in FileMount for that - so we just assume it referrs to the original
path instead.

Doing it in FileMount ends up being a little uglier, as we already do
all the exception wrangling in FileWrapper, so this'll do for now.

Fixes #495
This commit is contained in:
SquidDev 2020-07-18 10:06:23 +01:00
parent 2e9d6603e3
commit 8f069a9b72
2 changed files with 30 additions and 12 deletions

View File

@ -10,6 +10,7 @@
import dan200.computercraft.api.filesystem.IWritableMount;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.io.IOException;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.WritableByteChannel;
@ -85,7 +86,7 @@ public boolean exists( String path ) throws FileSystemException
}
catch( IOException e )
{
throw new FileSystemException( e.getMessage() );
throw localExceptionOf( path, e );
}
}
@ -98,7 +99,7 @@ public boolean isDirectory( String path ) throws FileSystemException
}
catch( IOException e )
{
throw localExceptionOf( e );
throw localExceptionOf( path, e );
}
}
@ -116,7 +117,7 @@ public void list( String path, List<String> contents ) throws FileSystemExceptio
}
catch( IOException e )
{
throw localExceptionOf( e );
throw localExceptionOf( path, e );
}
}
@ -130,7 +131,7 @@ public long getSize( String path ) throws FileSystemException
}
catch( IOException e )
{
throw localExceptionOf( e );
throw localExceptionOf( path, e );
}
}
@ -145,7 +146,7 @@ public BasicFileAttributes getAttributes( String path ) throws FileSystemExcepti
}
catch( IOException e )
{
throw localExceptionOf( e );
throw localExceptionOf( path, e );
}
}
@ -165,7 +166,7 @@ public ReadableByteChannel openForRead( String path ) throws FileSystemException
}
catch( IOException e )
{
throw localExceptionOf( e );
throw localExceptionOf( path, e );
}
}
@ -187,7 +188,7 @@ public void makeDirectory( String path ) throws FileSystemException
}
catch( IOException e )
{
throw localExceptionOf( e );
throw localExceptionOf( path, e );
}
}
@ -195,9 +196,9 @@ public void delete( String path ) throws FileSystemException
{
if( writableMount == null ) throw exceptionOf( path, "Access denied" );
path = toLocal( path );
try
{
path = toLocal( path );
if( mount.exists( path ) )
{
writableMount.delete( path );
@ -209,7 +210,7 @@ public void delete( String path ) throws FileSystemException
}
catch( IOException e )
{
throw localExceptionOf( e );
throw localExceptionOf( path, e );
}
}
@ -243,7 +244,7 @@ public WritableByteChannel openForWrite( String path ) throws FileSystemExceptio
}
catch( IOException e )
{
throw localExceptionOf( e );
throw localExceptionOf( path, e );
}
}
@ -281,7 +282,7 @@ else if( mount.isDirectory( path ) )
}
catch( IOException e )
{
throw localExceptionOf( e );
throw localExceptionOf( path, e );
}
}
@ -290,7 +291,7 @@ private String toLocal( String path )
return FileSystem.toLocal( path, location );
}
private FileSystemException localExceptionOf( IOException e )
private FileSystemException localExceptionOf( @Nullable String localPath, @Nonnull IOException e )
{
if( !location.isEmpty() && e instanceof FileOperationException )
{
@ -298,6 +299,14 @@ private FileSystemException localExceptionOf( IOException e )
if( ex.getFilename() != null ) return localExceptionOf( ex.getFilename(), ex.getMessage() );
}
if( e instanceof java.nio.file.FileSystemException )
{
// This error will contain the absolute path, leaking information about where MC is installed. We drop that,
// just taking the reason. We assume that the error refers to the input path.
String message = ((java.nio.file.FileSystemException) e).getReason().trim();
return localPath == null ? new FileSystemException( message ) : localExceptionOf( localPath, message );
}
return new FileSystemException( e.getMessage() );
}

View File

@ -99,6 +99,15 @@ describe("The fs library", function()
handle.close()
expect.error(handle.close):eq("attempt to use a closed file")
end)
it("fails gracefully when opening 'CON' on Windows", function()
local ok, err = fs.open("test-files/con", "w")
if ok then fs.delete("test-files/con") return end
-- On my Windows/Java version the message appears to be "Incorrect function.". It may not be
-- consistent though, and honestly doesn't matter too much.
expect(err):str_match("^/test%-files/con: .*")
end)
end)
describe("writing in binary mode", function()