From 062977336a45f90612e075f90d5eee7360c5e880 Mon Sep 17 00:00:00 2001 From: SquidDev Date: Fri, 10 Apr 2020 14:43:42 +0100 Subject: [PATCH] Handle missing file metadata on zip files - Return EPOCH if a zip entry's creation/modification/access time is missing. - If a BasicFileAttributes.*Time method returns null, use 0 as our time. This shouldn't happen, but is a good sanity check. Fixes #371 --- .../dan200/computercraft/core/apis/FSAPI.java | 10 ++++-- .../core/filesystem/JarMount.java | 15 +++++++-- .../core/filesystem/JarMountTest.java | 31 ++++++++++++++++--- 3 files changed, 46 insertions(+), 10 deletions(-) diff --git a/src/main/java/dan200/computercraft/core/apis/FSAPI.java b/src/main/java/dan200/computercraft/core/apis/FSAPI.java index 74f786f23..90a866a53 100644 --- a/src/main/java/dan200/computercraft/core/apis/FSAPI.java +++ b/src/main/java/dan200/computercraft/core/apis/FSAPI.java @@ -23,6 +23,7 @@ import java.io.BufferedWriter; import java.nio.channels.ReadableByteChannel; import java.nio.channels.WritableByteChannel; import java.nio.file.attribute.BasicFileAttributes; +import java.nio.file.attribute.FileTime; import java.util.HashMap; import java.util.Map; import java.util.OptionalLong; @@ -359,8 +360,8 @@ public class FSAPI implements ILuaAPI { BasicFileAttributes attributes = m_fileSystem.getAttributes( path ); Map result = new HashMap<>(); - result.put( "modification", attributes.lastModifiedTime().toMillis() ); - result.put( "created", attributes.creationTime().toMillis() ); + result.put( "modification", getFileTime( attributes.lastModifiedTime() ) ); + result.put( "created", getFileTime( attributes.creationTime() ) ); result.put( "size", attributes.isDirectory() ? 0 : attributes.size() ); result.put( "isDir", attributes.isDirectory() ); return new Object[] { result }; @@ -375,4 +376,9 @@ public class FSAPI implements ILuaAPI return null; } } + + private static long getFileTime( FileTime time ) + { + return time == null ? 0 : time.toMillis(); + } } diff --git a/src/main/java/dan200/computercraft/core/filesystem/JarMount.java b/src/main/java/dan200/computercraft/core/filesystem/JarMount.java index 2cf55a747..e2a1694e0 100644 --- a/src/main/java/dan200/computercraft/core/filesystem/JarMount.java +++ b/src/main/java/dan200/computercraft/core/filesystem/JarMount.java @@ -25,6 +25,7 @@ import java.nio.channels.Channels; import java.nio.channels.ReadableByteChannel; import java.nio.file.attribute.BasicFileAttributes; import java.nio.file.attribute.FileTime; +import java.time.Instant; import java.util.Enumeration; import java.util.HashMap; import java.util.List; @@ -290,19 +291,20 @@ public class JarMount implements IMount @Override public FileTime lastModifiedTime() { - return entry.getLastModifiedTime(); + return orEpoch( entry.getLastModifiedTime() ); } @Override public FileTime lastAccessTime() { - return entry.getLastAccessTime(); + return orEpoch( entry.getLastAccessTime() ); } @Override public FileTime creationTime() { - return entry.getCreationTime(); + FileTime time = entry.getCreationTime(); + return time == null ? lastModifiedTime() : time; } @Override @@ -340,5 +342,12 @@ public class JarMount implements IMount { return null; } + + private static final FileTime EPOCH = FileTime.from( Instant.EPOCH ); + + private static FileTime orEpoch( FileTime time ) + { + return time == null ? EPOCH : time; + } } } diff --git a/src/test/java/dan200/computercraft/core/filesystem/JarMountTest.java b/src/test/java/dan200/computercraft/core/filesystem/JarMountTest.java index 31031c96c..4fedb95b5 100644 --- a/src/test/java/dan200/computercraft/core/filesystem/JarMountTest.java +++ b/src/test/java/dan200/computercraft/core/filesystem/JarMountTest.java @@ -15,20 +15,24 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.nio.charset.StandardCharsets; +import java.nio.file.attribute.BasicFileAttributes; +import java.nio.file.attribute.FileTime; +import java.time.Instant; +import java.time.temporal.ChronoUnit; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; import static org.junit.jupiter.api.Assertions.*; -@SuppressWarnings( "deprecation" ) public class JarMountTest { private static final File ZIP_FILE = new File( "test-files/jar-mount.zip" ); + private static final FileTime MODIFY_TIME = FileTime.from( Instant.EPOCH.plus( 2, ChronoUnit.DAYS ) ); + @BeforeAll public static void before() throws IOException { - if( ZIP_FILE.exists() ) return; ZIP_FILE.getParentFile().mkdirs(); try( ZipOutputStream stream = new ZipOutputStream( new FileOutputStream( ZIP_FILE ) ) ) @@ -36,7 +40,7 @@ public class JarMountTest stream.putNextEntry( new ZipEntry( "dir/" ) ); stream.closeEntry(); - stream.putNextEntry( new ZipEntry( "dir/file.lua" ) ); + stream.putNextEntry( new ZipEntry( "dir/file.lua" ).setLastModifiedTime( MODIFY_TIME ) ); stream.write( "print('testing')".getBytes( StandardCharsets.UTF_8 ) ); stream.closeEntry(); } @@ -63,7 +67,7 @@ public class JarMountTest { IMount mount = new JarMount( ZIP_FILE, "dir/file.lua" ); byte[] contents; - try( InputStream stream = mount.openForRead( "" ) ) + try( @SuppressWarnings( "deprecation" ) InputStream stream = mount.openForRead( "" ) ) { contents = ByteStreams.toByteArray( stream ); } @@ -76,11 +80,28 @@ public class JarMountTest { IMount mount = new JarMount( ZIP_FILE, "dir" ); byte[] contents; - try( InputStream stream = mount.openForRead( "file.lua" ) ) + try( @SuppressWarnings( "deprecation" ) InputStream stream = mount.openForRead( "file.lua" ) ) { contents = ByteStreams.toByteArray( stream ); } assertEquals( new String( contents, StandardCharsets.UTF_8 ), "print('testing')" ); } + + @Test + public void fileAttributes() throws IOException + { + BasicFileAttributes attributes = new JarMount( ZIP_FILE, "dir" ).getAttributes( "file.lua" ); + assertFalse( attributes.isDirectory() ); + assertEquals( "print('testing')".length(), attributes.size() ); + assertEquals( MODIFY_TIME, attributes.lastModifiedTime() ); + } + + @Test + public void directoryAttributes() throws IOException + { + BasicFileAttributes attributes = new JarMount( ZIP_FILE, "dir" ).getAttributes( "" ); + assertTrue( attributes.isDirectory() ); + assertEquals( 0, attributes.size() ); + } }