Skip to content

Commit

Permalink
feat: FileSystemProvider::readAttributes faked posix support (#1067)
Browse files Browse the repository at this point in the history
  • Loading branch information
nielsbasjes committed Dec 9, 2022
1 parent 25ee1b7 commit b813ccc
Show file tree
Hide file tree
Showing 4 changed files with 112 additions and 5 deletions.
Expand Up @@ -64,9 +64,11 @@ public final class CloudStorageFileSystem extends FileSystem {
public static final String URI_SCHEME = "gs";
public static final String GCS_VIEW = "gcs";
public static final String BASIC_VIEW = "basic";
public static final String POSIX_VIEW = "posix";
public static final int BLOCK_SIZE_DEFAULT = 2 * 1024 * 1024;
public static final FileTime FILE_TIME_UNKNOWN = FileTime.fromMillis(0);
public static final Set<String> SUPPORTED_VIEWS = ImmutableSet.of(BASIC_VIEW, GCS_VIEW);
public static final Set<String> SUPPORTED_VIEWS =
ImmutableSet.of(BASIC_VIEW, GCS_VIEW, POSIX_VIEW);
private final CloudStorageFileSystemProvider provider;
private final String bucket;
private final CloudStorageConfiguration config;
Expand Down
Expand Up @@ -19,6 +19,12 @@
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Strings.isNullOrEmpty;
import static java.nio.file.attribute.PosixFilePermission.GROUP_EXECUTE;
import static java.nio.file.attribute.PosixFilePermission.GROUP_READ;
import static java.nio.file.attribute.PosixFilePermission.GROUP_WRITE;
import static java.nio.file.attribute.PosixFilePermission.OWNER_EXECUTE;
import static java.nio.file.attribute.PosixFilePermission.OWNER_READ;
import static java.nio.file.attribute.PosixFilePermission.OWNER_WRITE;

import com.google.api.gax.paging.Page;
import com.google.cloud.storage.Acl;
Expand Down Expand Up @@ -62,10 +68,13 @@
import java.nio.file.attribute.BasicFileAttributes;
import java.nio.file.attribute.FileAttribute;
import java.nio.file.attribute.FileAttributeView;
import java.nio.file.attribute.GroupPrincipal;
import java.nio.file.attribute.UserPrincipal;
import java.nio.file.spi.FileSystemProvider;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
Expand Down Expand Up @@ -852,7 +861,7 @@ public Map<String, Object> readAttributes(Path path, String attributes, LinkOpti
// (eg. BasicFileAttributeView and PosixFileAttributeView), so rather than a partial
// implementation we rely on the other overload for now.

// Partial implementation for a few commonly used ones: basic, gcs
// Partial implementation for a few commonly used ones: basic, gcs, posix
String[] split = attributes.split(":", 2);
if (split.length != 2) {
throw new UnsupportedOperationException();
Expand All @@ -868,6 +877,9 @@ public Map<String, Object> readAttributes(Path path, String attributes, LinkOpti
case "gcs":
fileAttributes = readAttributes(path, CloudStorageFileAttributes.class, options);
break;
case "posix":
// There is no real support for posix.
// Some systems expect Posix support for everything so these attributes are faked.
case "basic":
fileAttributes = readAttributes(path, BasicFileAttributes.class, options);
break;
Expand Down Expand Up @@ -905,6 +917,53 @@ public Map<String, Object> readAttributes(Path path, String attributes, LinkOpti
results.put("size", fileAttributes.size());
}

// There is no real support for posix.
// Some systems fail if there is no posix support at all.
// To let these systems use this FileSystem these attributes are faked.
if (view.equals("posix")) {
if (allAttributes || attributeNames.contains("owner")) {
results.put(
"owner",
new UserPrincipal() {
@Override
public String getName() {
return "fakeowner";
}

@Override
public String toString() {
return "fakeowner";
}
});
}
if (allAttributes || attributeNames.contains("group")) {
results.put(
"group",
new GroupPrincipal() {
@Override
public String getName() {
return "fakegroup";
}

@Override
public String toString() {
return "fakegroup";
}
});
}
if (allAttributes || attributeNames.contains("permissions")) {
if (fileAttributes.isRegularFile()) {
results.put("permissions", EnumSet.of(OWNER_READ, OWNER_WRITE, GROUP_READ, GROUP_WRITE));
} else {
// Directories, Symlinks and Other:
results.put(
"permissions",
EnumSet.of(
OWNER_READ, OWNER_WRITE, OWNER_EXECUTE, GROUP_READ, GROUP_WRITE, GROUP_EXECUTE));
}
}
}

// CloudStorageFileAttributes
if (fileAttributes instanceof CloudStorageFileAttributes) {
CloudStorageFileAttributes cloudStorageFileAttributes =
Expand Down
Expand Up @@ -59,6 +59,8 @@
import java.nio.file.Paths;
import java.nio.file.attribute.BasicFileAttributes;
import java.nio.file.attribute.FileTime;
import java.nio.file.attribute.GroupPrincipal;
import java.nio.file.attribute.UserPrincipal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
Expand Down Expand Up @@ -906,7 +908,51 @@ public void testReadAttributes() throws IOException {
assertEquals(
expectedSpecific,
fileSystemProvider.readAttributes(
path1, "basic:lastModifiedTime,isSymbolicLink,isOther,etag,cacheControl"));
path1, "basic:lastModifiedTime,isSymbolicLink,isOther,etag,cacheControl,owner,group"));

// Add the attributes that are only known in posix view
// These are all fake values
expectedSpecific.put(
"owner",
new UserPrincipal() {
@Override
public String getName() {
return "fakeowner";
}

@Override
public String toString() {
return "fakeowner";
}
});

expectedSpecific.put(
"group",
new GroupPrincipal() {
@Override
public String getName() {
return "fakegroup";
}

@Override
public String toString() {
return "fakegroup";
}
});

// The equals between two anonymous classes (the UserPrincipal and GroupPrincipal) is always
// false
// so we compare the toString() instead.
assertEquals(
expectedSpecific.toString(),
fileSystemProvider
.readAttributes(
path1,
"posix:lastModifiedTime,isSymbolicLink,isOther,etag,cacheControl,owner,group")
.toString());

expectedSpecific.remove("owner");
expectedSpecific.remove("group");

// Add the attributes that are only known in gcs view
expectedSpecific.put("etag", Optional.of("TheEtag"));
Expand All @@ -915,7 +961,7 @@ public void testReadAttributes() throws IOException {
assertEquals(
expectedSpecific,
fileSystemProvider.readAttributes(
path1, "gcs:lastModifiedTime,isSymbolicLink,isOther,etag,cacheControl"));
path1, "gcs:lastModifiedTime,isSymbolicLink,isOther,etag,cacheControl,owner,group"));
}

private static CloudStorageConfiguration permitEmptyPathComponents(boolean value) {
Expand Down
Expand Up @@ -179,7 +179,7 @@ public void testGetters() throws IOException {
assertThat(fs.getRootDirectories()).containsExactly(fs.getPath("/"));
assertThat(fs.getFileStores()).isEmpty();
assertThat(fs.getSeparator()).isEqualTo("/");
assertThat(fs.supportedFileAttributeViews()).containsExactly("basic", "gcs");
assertThat(fs.supportedFileAttributeViews()).containsExactly("basic", "gcs", "posix");
}
}

Expand Down

0 comments on commit b813ccc

Please sign in to comment.