diff --git a/modules/chimera/src/main/java/org/dcache/chimera/FsInode.java b/modules/chimera/src/main/java/org/dcache/chimera/FsInode.java index 4b286289b39..43bef0fc03b 100644 --- a/modules/chimera/src/main/java/org/dcache/chimera/FsInode.java +++ b/modules/chimera/src/main/java/org/dcache/chimera/FsInode.java @@ -18,6 +18,10 @@ import java.nio.ByteBuffer; import java.util.Arrays; +import java.util.List; +import java.util.Map; + +import org.dcache.acl.ACE; import org.dcache.chimera.posix.Stat; /** @@ -317,6 +321,14 @@ public FsInode mkdir(String name, int owner, int group, int mode) throws Chimera return _fs.mkdir(this, name, owner, group, mode); } + /** + * crate a directory with name 'newDir' in current inode with different access rights + */ + public FsInode mkdir(String name, int owner, int group, int mode, List acl, Map tags) + throws ChimeraFsException { + return _fs.mkdir(this, name, owner, group, mode, acl, tags); + } + /** * get inode of file in the current directory with name 'name' */ diff --git a/modules/chimera/src/main/java/org/dcache/chimera/FsSqlDriver.java b/modules/chimera/src/main/java/org/dcache/chimera/FsSqlDriver.java index 1dcee9b86c3..82ac2367240 100644 --- a/modules/chimera/src/main/java/org/dcache/chimera/FsSqlDriver.java +++ b/modules/chimera/src/main/java/org/dcache/chimera/FsSqlDriver.java @@ -2003,41 +2003,43 @@ boolean isTagOwner(Connection dbConnection, FsInode dir, String tagName) throws void createTags(Connection dbConnection, FsInode inode, int uid, int gid, int mode, Map tags) throws SQLException { - PreparedStatement stmt = null; - try { - Map ids = new HashMap<>(); - Timestamp now = new Timestamp(System.currentTimeMillis()); - - stmt = dbConnection.prepareStatement("INSERT INTO t_tags_inodes VALUES(?,?,1,?,?,?,?,?,?,?)"); - for (Map.Entry tag : tags.entrySet()) { - String id = UUID.randomUUID().toString().toUpperCase(); - ids.put(tag.getKey(), id); - byte[] value = tag.getValue(); - int len = value.length; - stmt.setString(1, id); - stmt.setInt(2, mode | UnixPermission.S_IFREG); - stmt.setInt(3, uid); - stmt.setInt(4, gid); - stmt.setLong(5, len); - stmt.setTimestamp(6, now); - stmt.setTimestamp(7, now); - stmt.setTimestamp(8, now); - stmt.setBinaryStream(9, new ByteArrayInputStream(value), len); - stmt.addBatch(); - } - stmt.executeBatch(); - stmt.close(); - - stmt = dbConnection.prepareStatement("INSERT INTO t_tags VALUES(?,?,?,1)"); - for (Map.Entry tag : ids.entrySet()) { - stmt.setString(1, inode.toString()); // ipnfsid - stmt.setString(2, tag.getKey()); // itagname - stmt.setString(3, tag.getValue()); // itagid - stmt.addBatch(); + if (!tags.isEmpty()) { + PreparedStatement stmt = null; + try { + Map ids = new HashMap<>(); + Timestamp now = new Timestamp(System.currentTimeMillis()); + + stmt = dbConnection.prepareStatement("INSERT INTO t_tags_inodes VALUES(?,?,1,?,?,?,?,?,?,?)"); + for (Map.Entry tag : tags.entrySet()) { + String id = UUID.randomUUID().toString().toUpperCase(); + ids.put(tag.getKey(), id); + byte[] value = tag.getValue(); + int len = value.length; + stmt.setString(1, id); + stmt.setInt(2, mode | UnixPermission.S_IFREG); + stmt.setInt(3, uid); + stmt.setInt(4, gid); + stmt.setLong(5, len); + stmt.setTimestamp(6, now); + stmt.setTimestamp(7, now); + stmt.setTimestamp(8, now); + stmt.setBinaryStream(9, new ByteArrayInputStream(value), len); + stmt.addBatch(); + } + stmt.executeBatch(); + stmt.close(); + + stmt = dbConnection.prepareStatement("INSERT INTO t_tags VALUES(?,?,?,1)"); + for (Map.Entry tag : ids.entrySet()) { + stmt.setString(1, inode.toString()); // ipnfsid + stmt.setString(2, tag.getKey()); // itagname + stmt.setString(3, tag.getValue()); // itagid + stmt.addBatch(); + } + stmt.executeBatch(); + } finally { + SqlHelper.tryToClose(stmt); } - stmt.executeBatch(); - } finally { - SqlHelper.tryToClose(stmt); } } diff --git a/modules/dcache-chimera/src/main/java/org/dcache/chimera/namespace/ChimeraNameSpaceProvider.java b/modules/dcache-chimera/src/main/java/org/dcache/chimera/namespace/ChimeraNameSpaceProvider.java index cb5b60137c4..ef309c71399 100644 --- a/modules/dcache-chimera/src/main/java/org/dcache/chimera/namespace/ChimeraNameSpaceProvider.java +++ b/modules/dcache-chimera/src/main/java/org/dcache/chimera/namespace/ChimeraNameSpaceProvider.java @@ -1085,6 +1085,25 @@ private ExtendedInode mkdir(Subject subject, ExtendedInode parent, String name, return parent.mkdir(name, uid, gid, mode); } + private ExtendedInode installSystemDirectory(FsPath path, int mode, List acl, Map tags) + throws ChimeraFsException, CacheException + { + ExtendedInode inode; + try { + inode = lookupDirectory(Subjects.ROOT, path); + } catch (FileNotFoundCacheException e) { + ExtendedInode parentOfPath = installDirectory(Subjects.ROOT, path.getParent(), 0, 0, mode); + try { + inode = parentOfPath.mkdir(path.getName(), 0, 0, mode, acl, tags); + } catch (FileExistsChimeraFsException e1) { + /* Concurrent directory creation. Do another lookup. + */ + inode = lookupDirectory(Subjects.ROOT, path); + } + } + return inode; + } + private ExtendedInode installDirectory(Subject subject, FsPath path, int uid, int gid, int mode) throws ChimeraFsException, CacheException { ExtendedInode inode; @@ -1226,7 +1245,7 @@ public FsPath createUploadPath(Subject subject, FsPath path, FsPath rootPath, /* Upload directory must exist and have the right permissions. */ - FsInode inodeOfUploadDir = installDirectory(Subjects.ROOT, uploadDirectory, 0, 0, 0711); + FsInode inodeOfUploadDir = installSystemDirectory(uploadDirectory, 0711, Collections.emptyList(), Collections.emptyMap()); if (inodeOfUploadDir.statCache().getUid() != 0) { _log.error("Owner must be root: {}", uploadDirectory); throw new CacheException("Owner must be root: " + uploadDirectory); diff --git a/modules/dcache-chimera/src/main/java/org/dcache/chimera/namespace/ExtendedInode.java b/modules/dcache-chimera/src/main/java/org/dcache/chimera/namespace/ExtendedInode.java index 972121e0395..41eefd3fe04 100644 --- a/modules/dcache-chimera/src/main/java/org/dcache/chimera/namespace/ExtendedInode.java +++ b/modules/dcache-chimera/src/main/java/org/dcache/chimera/namespace/ExtendedInode.java @@ -28,6 +28,7 @@ import java.io.IOException; import java.util.HashMap; +import java.util.List; import java.util.Map; import diskCacheV111.util.AccessLatency; @@ -35,6 +36,7 @@ import diskCacheV111.util.PnfsId; import diskCacheV111.util.RetentionPolicy; +import org.dcache.acl.ACE; import org.dcache.acl.ACL; import org.dcache.acl.enums.RsType; import org.dcache.chimera.ChimeraFsException; @@ -122,6 +124,13 @@ public ExtendedInode mkdir(String name, int owner, int group, int mode) throws C return new ExtendedInode(this, super.mkdir(name, owner, group, mode)); } + @Override + public ExtendedInode mkdir(String name, int owner, int group, int mode, List acl, Map tags) + throws ChimeraFsException + { + return new ExtendedInode(this, super.mkdir(name, owner, group, mode, acl, tags)); + } + @Override public ExtendedInode create(String name, int uid, int gid, int mode) throws ChimeraFsException {