Skip to content

Commit

Permalink
Add new ADVANCED permissions type
Browse files Browse the repository at this point in the history
This use MapDB to store UID/GID/Mask
  • Loading branch information
Toilal committed Dec 22, 2018
1 parent 9a263ec commit ee9039f
Show file tree
Hide file tree
Showing 34 changed files with 777 additions and 151 deletions.
27 changes: 21 additions & 6 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,13 @@
<artifactId>maven-clean-plugin</artifactId>
<version>3.1.0</version>
<configuration>
<filesets>
<fileset>
<directory>dist</directory>
</fileset>
</filesets>
<filesets>
<fileset>
<directory>dist</directory>
</fileset>
</filesets>
</configuration>
</plugin>
</plugin>
<plugin>
<groupId>com.akathist.maven.plugins.launch4j</groupId>
<artifactId>launch4j-maven-plugin</artifactId>
Expand Down Expand Up @@ -144,6 +144,21 @@
<artifactId>jimfs</artifactId>
<version>1.1</version>
</dependency>
<dependency>
<groupId>org.mapdb</groupId>
<artifactId>mapdb</artifactId>
<version>3.0.7</version>
</dependency>
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna</artifactId>
<version>5.1.0</version>
</dependency>
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna-platform</artifactId>
<version>5.1.0</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
Expand Down
19 changes: 12 additions & 7 deletions src/main/java/world/gfi/nfs4j/Daemon.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import world.gfi.nfs4j.api.Api;
import world.gfi.nfs4j.api.JsonTransformer;
import world.gfi.nfs4j.config.Config;
import world.gfi.nfs4j.config.PermissionsConfig;
import world.gfi.nfs4j.config.ShareConfig;
import world.gfi.nfs4j.exceptions.AttachException;
import world.gfi.nfs4j.fs.AttachableFileSystem;
Expand Down Expand Up @@ -48,7 +49,6 @@ public class Daemon implements Closeable {
private static final Logger LOG = LoggerFactory.getLogger(Daemon.class);

private final OncRpcSvc nfsSvc;
private final PermissionsMapper defaultPermissionsMapper;
private final DefaultPermissionsMapperFactory permissionsMapperFactory;
private final DefaultFileSystemFactory fsFactory;
private final UniqueAtomicLongGenerator uniqueHandleGenerator;
Expand Down Expand Up @@ -97,7 +97,6 @@ public Daemon(Config config) throws AttachException {
permissionsMapperFactory = new DefaultPermissionsMapperFactory();

vfs = new RootFileSystem(config.getPermissions(), uniqueHandleGenerator);
defaultPermissionsMapper = permissionsMapperFactory.newPermissionsMapper(config.getPermissions());
for (ShareConfig share : config.getShares()) {
attach(share);
}
Expand Down Expand Up @@ -125,17 +124,23 @@ public Daemon(Config config) throws AttachException {
}

public AttachableFileSystem attach(ShareConfig share) throws AttachException {
PermissionsMapper permissionsMapper = defaultPermissionsMapper;
if (share.getPermissions() != null) {
permissionsMapper = permissionsMapperFactory.newPermissionsMapper(share.getPermissions());
}
AttachableFileSystem shareVfs = fsFactory.newFileSystem(share.getPath(), permissionsMapper, uniqueHandleGenerator);
String alias = share.getAlias();
if (alias == null) {
alias = share.buildDefaultAlias();
} else if (share.isAppendDefaultAlias()) {
alias = alias + share.buildDefaultAlias();
}

PermissionsConfig permissions = share.getPermissions() == null ? this.config.getPermissions() : share.getPermissions();
PermissionsMapper permissionsMapper = null;

try {
permissionsMapper = permissionsMapperFactory.newPermissionsMapper(permissions, share, alias);
} catch (IOException e) {
throw new AttachException("Can't create permissions mapper", e);
}

AttachableFileSystem shareVfs = fsFactory.newFileSystem(share.getPath(), permissionsMapper, uniqueHandleGenerator);
vfs.attachFileSystem(shareVfs, alias);
share.setPath(shareVfs.getRoot());
share.setAlias(shareVfs.getAlias());
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/world/gfi/nfs4j/config/PermissionsConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@
import world.gfi.nfs4j.fs.permission.PermissionsMapperType;

public class PermissionsConfig {
PermissionsMapperType type = PermissionsMapperType.SIMPLE;
PermissionsMapperType type = PermissionsMapperType.ADVANCED;

int uid = 0;
int gid = 0;
int mask = 0755;
int mask = type == PermissionsMapperType.SIMPLE ? 0775 : 0664;

public PermissionsMapperType getType() {
return type;
Expand Down
9 changes: 9 additions & 0 deletions src/main/java/world/gfi/nfs4j/config/ShareConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ public class ShareConfig {
private Path path;
private String alias;
private boolean appendDefaultAlias;
private boolean localMetadata;
private PermissionsConfig permissions;

public ShareConfig() {
Expand Down Expand Up @@ -59,6 +60,14 @@ public void setAppendDefaultAlias(boolean appendDefaultAlias) {
this.appendDefaultAlias = appendDefaultAlias;
}

public boolean isLocalMetadata() {
return localMetadata;
}

public void setLocalMetadata(boolean localMetadata) {
this.localMetadata = localMetadata;
}

public PermissionsConfig getPermissions() {
return permissions;
}
Expand Down
17 changes: 13 additions & 4 deletions src/main/java/world/gfi/nfs4j/fs/AbstractNioFileSystem.java
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,15 @@ public AbstractNioFileSystem(Path root, PermissionsMapper permissionsMapper, Uni
this.handleRegistry = new PathHandleRegistry(handleGenerator);
this.rootFileHandle = handleRegistry.add(this.root);
this.fileSystemReaderWriter = new FileSystemReaderWriter(handleRegistry);
this.handleRegistry.setListener(this.permissionsMapper.getHandleRegistryListener());
}

abstract protected void applyOwnershipAndModeToPath(Path target, Subject subject, int mode) throws IOException;
@Override
public void close() throws IOException {
if (this.permissionsMapper.getClosable() != null) {
this.permissionsMapper.getClosable().close();
}
}

abstract protected A getFileAttributes(Path path) throws IOException;

Expand Down Expand Up @@ -121,6 +127,8 @@ protected void applyStatToPath(Stat stat, Path path) throws IOException {
}

attributeView.setTimes(lastModifiedTime, lastAccessTime, createTime);

this.permissionsMapper.writePermissions(path, stat);
}

protected void applyFileAttributesToStat(Stat stat, Path path, A attrs) throws IOException {
Expand Down Expand Up @@ -157,7 +165,7 @@ public Inode create(Inode parent, Type type, String path, Subject subject, int m
throw new ExistException("path " + newPath);
}

applyOwnershipAndModeToPath(newPath, subject, mode);
this.permissionsMapper.writePermissions(newPath, subject, mode);
return toInode(handleRegistry.toFileHandle(newPath));
}

Expand Down Expand Up @@ -269,7 +277,7 @@ public Inode mkdir(Inode parent, String path, Subject subject, int mode) throws
throw new ExistException("path " + newPath);
}

applyOwnershipAndModeToPath(newPath, subject, mode);
this.permissionsMapper.writePermissions(newPath, subject, mode);
return toInode(handleRegistry.toFileHandle(newPath));
}

Expand Down Expand Up @@ -349,7 +357,7 @@ public Inode symlink(Inode parent, String linkName, String targetName, Subject s
throw new ServerFaultException("Failed to create: " + e.getMessage(), e);
}

applyOwnershipAndModeToPath(link, subject, mode);
this.permissionsMapper.writePermissions(link, subject, mode);
return toInode(handleRegistry.toFileHandle(link));
}

Expand All @@ -373,6 +381,7 @@ protected Stat getStat(Path p) throws IOException {
A attrs = getFileAttributes(p);
Stat stat = new Stat();
applyFileAttributesToStat(stat, p, attrs);
this.permissionsMapper.readPermissions(p, attrs, stat);
return stat;
} catch (NoSuchFileException e) {
throw new NoEntException(p.toString());
Expand Down
3 changes: 2 additions & 1 deletion src/main/java/world/gfi/nfs4j/fs/AttachableFileSystem.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@
import org.dcache.nfs.vfs.Inode;
import org.dcache.nfs.vfs.VirtualFileSystem;

import java.io.Closeable;
import java.io.IOException;
import java.nio.file.Path;

/**
* Extension of {@link VirtualFileSystem} that supports attachement on {@link RootFileSystem}.
*/
public interface AttachableFileSystem extends VirtualFileSystem {
public interface AttachableFileSystem extends VirtualFileSystem, Closeable {
boolean hasInode(Inode inode);

Path getRoot();
Expand Down
12 changes: 2 additions & 10 deletions src/main/java/world/gfi/nfs4j/fs/LinuxNioFileSystem.java
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
package world.gfi.nfs4j.fs;

import world.gfi.nfs4j.fs.handle.UniqueHandleGenerator;
import world.gfi.nfs4j.fs.permission.PermissionsMapper;
import org.dcache.nfs.vfs.Stat;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import world.gfi.nfs4j.fs.handle.UniqueHandleGenerator;
import world.gfi.nfs4j.fs.permission.PermissionsMapper;

import javax.security.auth.Subject;
import java.io.IOException;
import java.nio.file.FileSystems;
import java.nio.file.Files;
Expand Down Expand Up @@ -40,13 +39,6 @@ protected PosixFileAttributes getFileAttributes(Path path) throws IOException {
protected void applyFileAttributesToStat(Stat stat, Path path, PosixFileAttributes attrs) throws IOException {
super.applyFileAttributesToStat(stat, path, attrs);
stat.setNlink((Integer) Files.getAttribute(path, "unix:nlink", NOFOLLOW_LINKS));

this.permissionsMapper.readPermissions(path, attrs, stat);
}

@Override
protected void applyOwnershipAndModeToPath(Path path, Subject subject, int mode) throws IOException {
this.permissionsMapper.writePermissions(path, subject, mode);
}

@Override
Expand Down
18 changes: 14 additions & 4 deletions src/main/java/world/gfi/nfs4j/fs/RootFileSystem.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,16 @@
import org.dcache.nfs.vfs.Inode;
import org.dcache.nfs.vfs.Stat;
import org.dcache.nfs.vfs.VirtualFileSystem;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import world.gfi.nfs4j.config.PermissionsConfig;
import world.gfi.nfs4j.exceptions.AliasAlreadyExistsException;
import world.gfi.nfs4j.exceptions.NoSuchAliasException;
import world.gfi.nfs4j.exceptions.AttachException;
import world.gfi.nfs4j.exceptions.AlreadyAttachedException;
import world.gfi.nfs4j.exceptions.AttachException;
import world.gfi.nfs4j.exceptions.NoSuchAliasException;
import world.gfi.nfs4j.fs.handle.UniqueHandleGenerator;
import world.gfi.nfs4j.fs.permission.SimpleLinuxPermissionsMapper;
import world.gfi.nfs4j.fs.permission.LinuxPermissionsSimpleReader;
import world.gfi.nfs4j.fs.permission.SimplePermissionsMapperRead;

import javax.security.auth.Subject;
import java.io.IOError;
Expand All @@ -34,6 +37,8 @@
* A memory implementation of {@link VirtualFileSystem} that supports attaching others file systems {@link AttachableFileSystem} on given aliases.
*/
public class RootFileSystem implements VirtualFileSystem {
private Logger LOG = LoggerFactory.getLogger(RootFileSystem.class);

private final LinuxNioFileSystem mainFs;
private Map<String, AttachableFileSystem> fileSystems = new LinkedHashMap<>();

Expand All @@ -47,7 +52,7 @@ private static Path buildRootPath() {
}

public RootFileSystem(PermissionsConfig permissions, UniqueHandleGenerator uniqueLongGenerator) {
mainFs = new LinuxNioFileSystem(buildRootPath(), new SimpleLinuxPermissionsMapper(permissions), uniqueLongGenerator);
mainFs = new LinuxNioFileSystem(buildRootPath(), new SimplePermissionsMapperRead(new LinuxPermissionsSimpleReader(permissions)), uniqueLongGenerator);
}

public AttachableFileSystem attachFileSystem(AttachableFileSystem fs, String path, String... morePath) throws AttachException {
Expand Down Expand Up @@ -78,6 +83,11 @@ public AttachableFileSystem detachFileSystem(String path, String... morePath) th
if (removedFileSystem == null) {
throw new NoSuchAliasException("No FileSystem found for alias " + aliasPath.toString());
}
try {
removedFileSystem.close();
} catch (IOException e) {
LOG.error("An error has occured while releasing resources associated to removed FileSystem", e);
}
return removedFileSystem;
}

Expand Down
12 changes: 2 additions & 10 deletions src/main/java/world/gfi/nfs4j/fs/WindowsNioFileSystem.java
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
package world.gfi.nfs4j.fs;

import world.gfi.nfs4j.fs.handle.UniqueHandleGenerator;
import world.gfi.nfs4j.fs.permission.PermissionsMapper;
import org.dcache.nfs.vfs.Stat;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import world.gfi.nfs4j.fs.handle.UniqueHandleGenerator;
import world.gfi.nfs4j.fs.permission.PermissionsMapper;

import javax.security.auth.Subject;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
Expand Down Expand Up @@ -34,12 +33,5 @@ protected DosFileAttributes getFileAttributes(Path path) throws IOException {
protected void applyFileAttributesToStat(Stat stat, Path path, DosFileAttributes attrs) throws IOException {
super.applyFileAttributesToStat(stat, path, attrs);
stat.setNlink(1);

this.permissionsMapper.readPermissions(path, attrs, stat);
}

@Override
protected void applyOwnershipAndModeToPath(Path target, Subject subject, int mode) throws IOException {
this.permissionsMapper.writePermissions(target, subject, mode);
}
}
17 changes: 17 additions & 0 deletions src/main/java/world/gfi/nfs4j/fs/handle/HandleRegistry.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ public abstract class HandleRegistry<P> {
private final NonBlockingHashMapLong<P> fileHandleToPath = new NonBlockingHashMapLong<>();
private final NonBlockingHashMap<P, Long> pathToFileHandle = new NonBlockingHashMap<>();
private final UniqueHandleGenerator uniqueLongGenerator;
private HandleRegistryListener<P> listener;

public void setListener(HandleRegistryListener<P> listener) {
this.listener = listener;
}

public HandleRegistry(UniqueHandleGenerator uniqueLongGenerator) {
this.uniqueLongGenerator = uniqueLongGenerator;
Expand Down Expand Up @@ -101,6 +106,10 @@ private long add(P path, long fileHandle) {
throw new IllegalStateException("Can't add FileHandle " + fileHandle + " with Path " + path + ". FileHandle " + fileHandle + " is already registered with Path " + existingPath);
}

if (this.listener != null) {
this.listener.added(path, fileHandle);
}

return fileHandle;
}

Expand All @@ -120,6 +129,10 @@ protected boolean replaceItem(P oldPath, P newPath) {
return false;
}

if (this.listener != null) {
this.listener.replaced(oldPath, newPath);
}

return true;
}

Expand All @@ -135,6 +148,10 @@ public long remove(P path) {
throw new IllegalStateException("Can't remove Path " + path + ". Removed Path " + removedPath + " doesn't match expected path " + path + ".");
}

if (this.listener != null) {
this.listener.removed(path, (long) fileHandle);
}

return fileHandle;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package world.gfi.nfs4j.fs.handle;

public interface HandleRegistryListener<P> {
void added(P path, long fileHandle);

void removed(P path, long fileHandle);

void replaced(P oldPath, P newPath);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package world.gfi.nfs4j.fs.handle;

import java.nio.file.Path;

public interface PathHandleRegistryListener extends HandleRegistryListener<Path> {
}
Loading

0 comments on commit ee9039f

Please sign in to comment.