diff --git a/core/src/main/java/io/roastedroot/zerofs/PosixAttributeProvider.java b/core/src/main/java/io/roastedroot/zerofs/PosixAttributeProvider.java index 2213de05b..7b44aa8aa 100644 --- a/core/src/main/java/io/roastedroot/zerofs/PosixAttributeProvider.java +++ b/core/src/main/java/io/roastedroot/zerofs/PosixAttributeProvider.java @@ -13,6 +13,10 @@ import java.nio.file.attribute.PosixFilePermission; import java.nio.file.attribute.PosixFilePermissions; import java.nio.file.attribute.UserPrincipal; +import java.util.Collection; +import java.util.Collections; +import java.util.EnumSet; +import java.util.LinkedHashSet; import java.util.Map; import java.util.Objects; import java.util.Set; @@ -31,7 +35,7 @@ final class PosixAttributeProvider extends AttributeProvider { private static final GroupPrincipal DEFAULT_GROUP = createGroupPrincipal("group"); private static final Set DEFAULT_PERMISSIONS = - Set.copyOf(PosixFilePermissions.fromString("rw-r--r--")); + immutablePermissions(PosixFilePermissions.fromString("rw-r--r--")); @Override public String name() { @@ -74,7 +78,7 @@ public Set fixedAttributes() { if (userProvidedPermissions != null) { if (userProvidedPermissions instanceof String) { permissions = - Set.copyOf( + immutablePermissions( PosixFilePermissions.fromString((String) userProvidedPermissions)); } else if (userProvidedPermissions instanceof Set) { permissions = toPermissions((Set) userProvidedPermissions); @@ -140,7 +144,14 @@ private static Set toPermissions(Set set) { } } - return Set.copyOf((Set) copy); + return immutablePermissions((Set) copy); + } + + private static Set immutablePermissions( + Collection permissions) { + Set result = EnumSet.noneOf(PosixFilePermission.class); + result.addAll(permissions); + return Collections.unmodifiableSet(result); } @Override @@ -201,7 +212,7 @@ public void setTimes( @Override public void setPermissions(Set perms) throws IOException { - lookupFile().setAttribute("posix", "permissions", Set.copyOf(perms)); + lookupFile().setAttribute("posix", "permissions", immutablePermissions(perms)); } @Override @@ -248,7 +259,7 @@ public GroupPrincipal group() { @Override public Set permissions() { - return permissions; + return new LinkedHashSet<>(permissions); } } } diff --git a/core/src/main/java/io/roastedroot/zerofs/UserDefinedAttributeProvider.java b/core/src/main/java/io/roastedroot/zerofs/UserDefinedAttributeProvider.java index e948c87bb..6244af8fb 100644 --- a/core/src/main/java/io/roastedroot/zerofs/UserDefinedAttributeProvider.java +++ b/core/src/main/java/io/roastedroot/zerofs/UserDefinedAttributeProvider.java @@ -4,6 +4,7 @@ import java.nio.ByteBuffer; import java.nio.file.attribute.FileAttributeView; import java.nio.file.attribute.UserDefinedFileAttributeView; +import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Objects; @@ -49,7 +50,7 @@ private static Set userDefinedAttributes(File file) { for (String attribute : file.getAttributeNames("user")) { builder.add(attribute); } - return Set.copyOf(builder); + return Collections.unmodifiableSet(builder); } @Override diff --git a/core/src/test/java/io/roastedroot/zerofs/PosixAttributeProviderTest.java b/core/src/test/java/io/roastedroot/zerofs/PosixAttributeProviderTest.java index 3cd36f6d9..ebdac9737 100644 --- a/core/src/test/java/io/roastedroot/zerofs/PosixAttributeProviderTest.java +++ b/core/src/test/java/io/roastedroot/zerofs/PosixAttributeProviderTest.java @@ -10,6 +10,8 @@ import java.nio.file.attribute.PosixFileAttributes; import java.nio.file.attribute.PosixFilePermission; import java.nio.file.attribute.PosixFilePermissions; +import java.util.ArrayList; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; @@ -107,4 +109,22 @@ public void testAttributes() { assertEquals(createGroupPrincipal("group"), attrs.group()); assertEquals(0, attrs.fileKey()); } + + @Test + public void testAttributes_permissionsAreModifiable() { + Set permissions = provider.readAttributes(file).permissions(); + permissions.add(PosixFilePermission.OWNER_EXECUTE); + assertEquals(PosixFilePermissions.fromString("rwxr--r--"), permissions); + } + + @Test + public void testAttributes_permissionsInEnumOrder() { + provider.set(file, "posix", "permissions", new HashSet<>(allPermissions()), false); + assertEquals( + allPermissions(), new ArrayList<>(provider.readAttributes(file).permissions())); + } + + private static List allPermissions() { + return List.of(PosixFilePermission.values()); + } } diff --git a/core/src/test/java/io/roastedroot/zerofs/UserDefinedAttributeProviderTest.java b/core/src/test/java/io/roastedroot/zerofs/UserDefinedAttributeProviderTest.java index 7d2a130a4..2a76bb56c 100644 --- a/core/src/test/java/io/roastedroot/zerofs/UserDefinedAttributeProviderTest.java +++ b/core/src/test/java/io/roastedroot/zerofs/UserDefinedAttributeProviderTest.java @@ -59,6 +59,19 @@ public void testSetOnCreate() { assertSetFailsOnCreate("anything", new byte[0]); } + @Test + public void testView_listIsSorted() throws IOException { + UserDefinedFileAttributeView view = provider.view(fileLookup(), NO_INHERITED_VIEWS); + List names = + List.of( + "alpha", "bravo", "charlie", "delta", "echo", "foxtrot", "golf", "hotel", + "india", "juliett"); + for (String name : names) { + view.write(name, ByteBuffer.wrap(new byte[] {1})); + } + assertEquals(names, view.list()); + } + @Test public void testView() throws IOException { UserDefinedFileAttributeView view = provider.view(fileLookup(), NO_INHERITED_VIEWS);