Return-Path: X-Original-To: apmail-cassandra-commits-archive@www.apache.org Delivered-To: apmail-cassandra-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 35A6710198 for ; Wed, 27 Nov 2013 18:38:06 +0000 (UTC) Received: (qmail 26028 invoked by uid 500); 27 Nov 2013 18:38:02 -0000 Delivered-To: apmail-cassandra-commits-archive@cassandra.apache.org Received: (qmail 25986 invoked by uid 500); 27 Nov 2013 18:37:57 -0000 Mailing-List: contact commits-help@cassandra.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@cassandra.apache.org Delivered-To: mailing list commits@cassandra.apache.org Received: (qmail 25966 invoked by uid 99); 27 Nov 2013 18:37:45 -0000 Received: from tyr.zones.apache.org (HELO tyr.zones.apache.org) (140.211.11.114) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 27 Nov 2013 18:37:45 +0000 Received: by tyr.zones.apache.org (Postfix, from userid 65534) id ECC2E90EB32; Wed, 27 Nov 2013 18:37:44 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: jbellis@apache.org To: commits@cassandra.apache.org Message-Id: <0ca80598ad084b1dbb03811b3ed32701@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: git commit: validate directory permissions on startup Patch by Lyuben Todorov and Koray Sariteke; reviewed by Mikhail Stepura for CASSANDRA-5818 Date: Wed, 27 Nov 2013 18:37:44 +0000 (UTC) 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 Authored: Wed Nov 27 12:37:31 2013 -0600 Committer: Jonathan Ellis 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