aboutsummaryrefslogtreecommitdiffstats
path: root/testutil/src
diff options
context:
space:
mode:
authorValerij Fredriksen <valerijf@yahooinc.com>2021-10-06 16:35:46 +0200
committerValerij Fredriksen <valerijf@yahooinc.com>2021-10-07 11:38:45 +0200
commit3eca0e27fb4932c56a8401f88f151b454a105e44 (patch)
treec49f330952ebfb80aacd711741d36ba2e8e096e7 /testutil/src
parent8d7e6943196e1cfd298cf6139178d0e6ed5a24f0 (diff)
Create custom fs attribute provider for uid/gid
Diffstat (limited to 'testutil/src')
-rw-r--r--testutil/src/main/java/com/yahoo/vespa/test/file/TestFileSystem.java5
-rw-r--r--testutil/src/main/java/com/yahoo/vespa/test/file/UnixUidGidAttributeProvider.java161
2 files changed, 163 insertions, 3 deletions
diff --git a/testutil/src/main/java/com/yahoo/vespa/test/file/TestFileSystem.java b/testutil/src/main/java/com/yahoo/vespa/test/file/TestFileSystem.java
index 65d3498a5dd..bd2f3161209 100644
--- a/testutil/src/main/java/com/yahoo/vespa/test/file/TestFileSystem.java
+++ b/testutil/src/main/java/com/yahoo/vespa/test/file/TestFileSystem.java
@@ -1,5 +1,4 @@
// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-
package com.yahoo.vespa.test.file;
import com.google.common.jimfs.Configuration;
@@ -12,11 +11,11 @@ import java.nio.file.FileSystem;
public class TestFileSystem {
public static FileSystem create() {
// This configuration is based on Configuration.unix(), except:
- // - Use "posix" attribute view which is necessary for permissions, owner, and group.
+ // - Use custom attribute provider view which is necessary for uid and gid.
Configuration configuration = Configuration.builder(PathType.unix())
.setRoots("/")
.setWorkingDirectory("/work")
- .setAttributeViews("posix")
+ .addAttributeProvider(new UnixUidGidAttributeProvider())
.setSupportedFeatures(Feature.LINKS, Feature.SYMBOLIC_LINKS, Feature.SECURE_DIRECTORY_STREAM, Feature.FILE_CHANNEL)
.build();
return Jimfs.newFileSystem(configuration);
diff --git a/testutil/src/main/java/com/yahoo/vespa/test/file/UnixUidGidAttributeProvider.java b/testutil/src/main/java/com/yahoo/vespa/test/file/UnixUidGidAttributeProvider.java
new file mode 100644
index 00000000000..2b1b0231b4f
--- /dev/null
+++ b/testutil/src/main/java/com/yahoo/vespa/test/file/UnixUidGidAttributeProvider.java
@@ -0,0 +1,161 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.yahoo.vespa.test.file;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.jimfs.AttributeProvider;
+import com.google.common.jimfs.File;
+import com.google.common.jimfs.FileLookup;
+
+import java.nio.file.attribute.FileAttributeView;
+import java.nio.file.attribute.FileTime;
+import java.nio.file.attribute.GroupPrincipal;
+import java.nio.file.attribute.PosixFilePermission;
+import java.nio.file.attribute.UserPrincipal;
+import java.util.Optional;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Same as {@code com.google.common.jimfs.UnixAttributeProvider} except that getUniqueId() will return user
+ * if user is a numerical string.
+ */
+public class UnixUidGidAttributeProvider extends AttributeProvider {
+
+ private static final ImmutableSet<String> ATTRIBUTES = ImmutableSet.of("uid", "ino", "dev", "nlink", "rdev", "ctime", "mode", "gid");
+ private static final ImmutableSet<String> INHERITED_VIEWS = ImmutableSet.of("basic", "owner", "posix");
+
+ private final AtomicInteger uidGenerator = new AtomicInteger();
+ private final ConcurrentMap<UserPrincipal, Integer> idCache = new ConcurrentHashMap<>();
+
+ @Override
+ public String name() {
+ return "unix";
+ }
+
+ @Override
+ public ImmutableSet<String> inherits() {
+ return INHERITED_VIEWS;
+ }
+
+ @Override
+ public ImmutableSet<String> fixedAttributes() {
+ return ATTRIBUTES;
+ }
+
+ @Override
+ public Class<UnixFileAttributeView> viewType() {
+ return UnixFileAttributeView.class;
+ }
+
+ @Override
+ public UnixFileAttributeView view(FileLookup lookup, ImmutableMap<String, FileAttributeView> inheritedViews) {
+ throw new UnsupportedOperationException();
+ }
+
+ private int getUniqueId(UserPrincipal user) {
+ return idCache.computeIfAbsent(user, id -> maybeNumber(id.getName()).orElseGet(uidGenerator::incrementAndGet));
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public Object get(File file, String attribute) {
+ switch (attribute) {
+ case "uid":
+ UserPrincipal user = (UserPrincipal) file.getAttribute("owner", "owner");
+ return getUniqueId(user);
+ case "gid":
+ GroupPrincipal group = (GroupPrincipal) file.getAttribute("posix", "group");
+ return getUniqueId(group);
+ case "mode":
+ Set<PosixFilePermission> permissions =
+ (Set<PosixFilePermission>) file.getAttribute("posix", "permissions");
+ return toMode(permissions);
+ case "ctime":
+ return FileTime.fromMillis(file.getCreationTime());
+ case "rdev":
+ return 0L;
+ case "dev":
+ return 1L;
+ case "ino":
+ return file.id();
+ case "nlink":
+ return file.links();
+ default:
+ return null;
+ }
+ }
+
+ @Override
+ public void set(File file, String view, String attribute, Object value, boolean create) {
+ throw unsettable(view, attribute);
+ }
+
+ @SuppressWarnings("OctalInteger")
+ private static int toMode(Set<PosixFilePermission> permissions) {
+ int result = 0;
+ for (PosixFilePermission permission : permissions) {
+ checkNotNull(permission);
+ switch (permission) {
+ case OWNER_READ:
+ result |= 0400;
+ break;
+ case OWNER_WRITE:
+ result |= 0200;
+ break;
+ case OWNER_EXECUTE:
+ result |= 0100;
+ break;
+ case GROUP_READ:
+ result |= 0040;
+ break;
+ case GROUP_WRITE:
+ result |= 0020;
+ break;
+ case GROUP_EXECUTE:
+ result |= 0010;
+ break;
+ case OTHERS_READ:
+ result |= 0004;
+ break;
+ case OTHERS_WRITE:
+ result |= 0002;
+ break;
+ case OTHERS_EXECUTE:
+ result |= 0001;
+ break;
+ default:
+ throw new AssertionError(); // no other possible values
+ }
+ }
+ return result;
+ }
+
+ interface UnixFileAttributeView extends FileAttributeView {}
+
+ private static Optional<Integer> maybeNumber(String str) {
+ try {
+ return Optional.of(Integer.parseInt(str));
+ } catch (NumberFormatException e) {
+ return Optional.empty();
+ }
+ }
+}