aboutsummaryrefslogtreecommitdiff
path: root/src/libstore
diff options
context:
space:
mode:
authorEelco Dolstra <e.dolstra@tudelft.nl>2004-10-25 14:38:23 +0000
committerEelco Dolstra <e.dolstra@tudelft.nl>2004-10-25 14:38:23 +0000
commitf4d44a002688262d33093494a7fea1bb11b97ac9 (patch)
tree9768179865220106bd1c0103361ded0967c059c8 /src/libstore
parent3ade3e7721df981614bbb2420baeb84e58085967 (diff)
* Allow certain operations to succeed even if we don't have write
permission to the Nix store or database. E.g., `nix-env -qa' will work, but `nix-env -qas' won't (the latter needs DB access). The option `--readonly-mode' forces this mode; otherwise, it's only activated when the database cannot be opened.
Diffstat (limited to 'src/libstore')
-rw-r--r--src/libstore/db.cc13
-rw-r--r--src/libstore/db.hh7
-rw-r--r--src/libstore/globals.cc2
-rw-r--r--src/libstore/globals.hh4
-rw-r--r--src/libstore/store.cc24
-rw-r--r--src/libstore/storeexpr.cc2
6 files changed, 42 insertions, 10 deletions
diff --git a/src/libstore/db.cc b/src/libstore/db.cc
index f01cefd79..3b7bddaa2 100644
--- a/src/libstore/db.cc
+++ b/src/libstore/db.cc
@@ -1,6 +1,7 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
+#include <errno.h>
#include <memory>
@@ -81,12 +82,16 @@ void Transaction::moveTo(Transaction & t)
void Database::requireEnv()
{
checkInterrupt();
- if (!env) throw Error("database environment not open");
+ if (!env)throw Error("database environment is not open "
+ "(maybe you don't have sufficient permission?)");
}
Db * Database::getDb(TableId table)
{
+ if (table == 0)
+ throw Error("database table is not open "
+ "(maybe you don't have sufficient permission?)");
map<TableId, Db *>::iterator i = tables.find(table);
if (i == tables.end())
throw Error("unknown table id");
@@ -210,7 +215,11 @@ void Database::open(const string & path)
string accessorsPath = path + "/accessor_count";
fdAccessors = ::open(accessorsPath.c_str(), O_RDWR | O_CREAT, 0666);
if (fdAccessors == -1)
- throw SysError(format("opening file `%1%'") % accessorsPath);
+ if (errno == EACCES)
+ throw DbNoPermission(
+ format("permission denied to database in `%1%'") % accessorsPath);
+ else
+ throw SysError(format("opening file `%1%'") % accessorsPath);
/* Open the lock file. */
string lockPath = path + "/access_lock";
diff --git a/src/libstore/db.hh b/src/libstore/db.hh
index bbeabfc7d..d566fdad1 100644
--- a/src/libstore/db.hh
+++ b/src/libstore/db.hh
@@ -87,4 +87,11 @@ public:
};
+class DbNoPermission : public Error
+{
+public:
+ DbNoPermission(const format & f) : Error(f) { };
+};
+
+
#endif /* !__DB_H */
diff --git a/src/libstore/globals.cc b/src/libstore/globals.cc
index 44794d147..52f2a0a0b 100644
--- a/src/libstore/globals.cc
+++ b/src/libstore/globals.cc
@@ -15,3 +15,5 @@ bool tryFallback = false;
Verbosity buildVerbosity = lvlInfo;
unsigned int maxBuildJobs = 1;
+
+bool readOnlyMode = false;
diff --git a/src/libstore/globals.hh b/src/libstore/globals.hh
index 7f88d5c53..beaa0acc9 100644
--- a/src/libstore/globals.hh
+++ b/src/libstore/globals.hh
@@ -43,5 +43,9 @@ extern Verbosity buildVerbosity;
/* Maximum number of parallel build jobs. 0 means unlimited. */
extern unsigned int maxBuildJobs;
+/* Read-only mode. Don't copy stuff to the store, don't change the
+ database. */
+extern bool readOnlyMode;
+
#endif /* !__GLOBALS_H */
diff --git a/src/libstore/store.cc b/src/libstore/store.cc
index 1f05b63a6..7dbf520d2 100644
--- a/src/libstore/store.cc
+++ b/src/libstore/store.cc
@@ -21,7 +21,7 @@ static Database nixDB;
The existence of a key $p$ indicates that path $p$ is valid (that
is, produced by a succesful build). */
-static TableId dbValidPaths;
+static TableId dbValidPaths = 0;
/* dbSuccessors :: Path -> Path
@@ -32,14 +32,14 @@ static TableId dbValidPaths;
Note that a term $y$ is a successor of $x$ iff there exists a
sequence of rewrite steps that rewrites $x$ into $y$.
*/
-static TableId dbSuccessors;
+static TableId dbSuccessors = 0;
/* dbSuccessorsRev :: Path -> [Path]
The reverse mapping of dbSuccessors (i.e., it stores the
predecessors of a Nix expression).
*/
-static TableId dbSuccessorsRev;
+static TableId dbSuccessorsRev = 0;
/* dbSubstitutes :: Path -> [(Path, Path, [string])]
@@ -54,14 +54,14 @@ static TableId dbSuccessorsRev;
substitute for that derivate. The substitute in this case might be
a Nix expression that fetches the Nix archive.
*/
-static TableId dbSubstitutes;
+static TableId dbSubstitutes = 0;
/* dbSubstitutesRev :: Path -> [Path]
The reverse mapping of dbSubstitutes; it maps store expressions
back to the paths for which they are substitutes.
*/
-static TableId dbSubstitutesRev;
+static TableId dbSubstitutesRev = 0;
bool Substitute::operator == (const Substitute & sub)
@@ -74,7 +74,14 @@ bool Substitute::operator == (const Substitute & sub)
void openDB()
{
- nixDB.open(nixDBPath);
+ if (readOnlyMode) return;
+ try {
+ nixDB.open(nixDBPath);
+ } catch (DbNoPermission & e) {
+ printMsg(lvlTalkative, "cannot access Nix database; continuing anyway");
+ readOnlyMode = true;
+ return;
+ }
dbValidPaths = nixDB.openTable("validpaths");
dbSuccessors = nixDB.openTable("successors");
dbSuccessorsRev = nixDB.openTable("successors-rev");
@@ -433,7 +440,7 @@ Path addToStore(const Path & _srcPath)
string baseName = baseNameOf(srcPath);
Path dstPath = canonPath(nixStore + "/" + (string) h + "-" + baseName);
- if (!isValidPath(dstPath)) {
+ if (!readOnlyMode && !isValidPath(dstPath)) {
/* The first check above is an optimisation to prevent
unnecessary lock acquisition. */
@@ -445,6 +452,9 @@ Path addToStore(const Path & _srcPath)
if (!isValidPath(dstPath)) {
if (pathExists(dstPath)) deletePath(dstPath);
+
+ /* !!! race: srcPath might change between hashPath() and
+ here! */
copyPath(srcPath, dstPath);
diff --git a/src/libstore/storeexpr.cc b/src/libstore/storeexpr.cc
index 45b5af055..29f271de8 100644
--- a/src/libstore/storeexpr.cc
+++ b/src/libstore/storeexpr.cc
@@ -17,7 +17,7 @@ Path writeTerm(ATerm t, const string & suffix)
Path path = canonPath(nixStore + "/" +
(string) h + suffix + ".store");
- if (!isValidPath(path)) {
+ if (!readOnlyMode && !isValidPath(path)) {
char * s = ATwriteToString(t);
if (!s) throw Error(format("cannot write aterm to `%1%'") % path);
addTextToStore(path, string(s));