Updated Branches: refs/heads/trunk f1a67a06a -> 351d49b06
validate directory permissions on startup Patch by Lyuben Todorov and Koray Sariteke; reviewed by Mikhail Stepura for CASSANDRA-5818 Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/351d49b0 Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/351d49b0 Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/351d49b0 Branch: refs/heads/trunk Commit: 351d49b06bd6887447eecb149b3cdf1697ab41ac Parents: f1a67a0 Author: Jonathan Ellis <[email protected]> Authored: Wed Nov 27 12:37:31 2013 -0600 Committer: Jonathan Ellis <[email protected]> Committed: Wed Nov 27 12:37:40 2013 -0600 ---------------------------------------------------------------------- .../org/apache/cassandra/db/Directories.java | 74 ++++++++++++++++++++ .../cassandra/service/CassandraDaemon.java | 22 +++++- 2 files changed, 93 insertions(+), 3 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cassandra/blob/351d49b0/src/java/org/apache/cassandra/db/Directories.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/db/Directories.java b/src/java/org/apache/cassandra/db/Directories.java index ea5c2f4..0c8f1d9 100644 --- a/src/java/org/apache/cassandra/db/Directories.java +++ b/src/java/org/apache/cassandra/db/Directories.java @@ -88,6 +88,80 @@ public class Directories dataFileLocations[i] = new DataDirectory(new File(locations[i])); } + + /** + * Checks whether Cassandra has RWX permissions to the specified directory. Logs an error with + * the details if it does not. + * + * @param dir File object of the directory. + * @param dataDir String representation of the directory's location + * @return status representing Cassandra's RWX permissions to the supplied folder location. + */ + public static boolean verifyFullPermissions(File dir, String dataDir) + { + if (!dir.isDirectory()) + { + logger.error("Not a directory {}", dataDir); + return false; + } + else if (!FileAction.hasPrivilege(dir, FileAction.X)) + { + logger.error("Doesn't have execute permissions for {} directory", dataDir); + return false; + } + else if (!FileAction.hasPrivilege(dir, FileAction.R)) + { + logger.error("Doesn't have read permissions for {} directory", dataDir); + return false; + } + else if (dir.exists() && !FileAction.hasPrivilege(dir, FileAction.W)) + { + logger.error("Doesn't have write permissions for {} directory", dataDir); + return false; + } + + return true; + } + + public enum FileAction + { + X, W, XW, R, XR, RW, XRW; + + private FileAction() + { + } + + public static boolean hasPrivilege(File file, FileAction action) + { + boolean privilege = false; + + switch (action) { + case X: + privilege = file.canExecute(); + break; + case W: + privilege = file.canWrite(); + break; + case XW: + privilege = file.canExecute() && file.canWrite(); + break; + case R: + privilege = file.canRead(); + break; + case XR: + privilege = file.canExecute() && file.canRead(); + break; + case RW: + privilege = file.canRead() && file.canWrite(); + break; + case XRW: + privilege = file.canExecute() && file.canRead() && file.canWrite(); + break; + } + return privilege; + } + } + private final String keyspacename; private final String cfname; private final File[] sstableDirectories; http://git-wip-us.apache.org/repos/asf/cassandra/blob/351d49b0/src/java/org/apache/cassandra/service/CassandraDaemon.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/service/CassandraDaemon.java b/src/java/org/apache/cassandra/service/CassandraDaemon.java index cb3cc88..ffff006 100644 --- a/src/java/org/apache/cassandra/service/CassandraDaemon.java +++ b/src/java/org/apache/cassandra/service/CassandraDaemon.java @@ -38,6 +38,7 @@ import org.apache.cassandra.config.CFMetaData; import org.apache.cassandra.config.DatabaseDescriptor; import org.apache.cassandra.config.Schema; import org.apache.cassandra.db.ColumnFamilyStore; +import org.apache.cassandra.db.Directories; import org.apache.cassandra.db.Keyspace; import org.apache.cassandra.db.MeteredFlusher; import org.apache.cassandra.db.SystemKeyspace; @@ -157,9 +158,24 @@ public class CassandraDaemon { logger.debug("Checking directory {}", dataDir); File dir = new File(dataDir); - if (dir.exists()) - assert dir.isDirectory() && dir.canRead() && dir.canWrite() && dir.canExecute() - : String.format("Directory %s is not accessible.", dataDir); + + // check that directories exist. + if (!dir.exists()) + { + logger.error("Directory {} doesn't exist", dataDir); + // if they don't, failing their creation, stop cassandra. + if (!dir.mkdirs()) + { + logger.error("Has no permission to create {} directory", dataDir); + System.exit(3); + } + } + // if directories exist verify their permissions + if (!Directories.verifyFullPermissions(dir, dataDir)) + { + // if permissions aren't sufficient, stop cassandra. + System.exit(3); + } } if (CacheService.instance == null) // should never happen
