Make readDirectory() return inode / file type

This commit is contained in:
Eelco Dolstra 2014-08-01 16:37:47 +02:00
parent 1c208f2b7e
commit daf3f2c11f
7 changed files with 48 additions and 46 deletions

View file

@ -230,11 +230,11 @@ static void readTempRoots(PathSet & tempRoots, FDs & fds)
{ {
/* Read the `temproots' directory for per-process temporary root /* Read the `temproots' directory for per-process temporary root
files. */ files. */
Strings tempRootFiles = readDirectory( DirEntries tempRootFiles = readDirectory(
(format("%1%/%2%") % settings.nixStateDir % tempRootsDir).str()); (format("%1%/%2%") % settings.nixStateDir % tempRootsDir).str());
foreach (Strings::iterator, i, tempRootFiles) { for (auto & i : tempRootFiles) {
Path path = (format("%1%/%2%/%3%") % settings.nixStateDir % tempRootsDir % *i).str(); Path path = (format("%1%/%2%/%3%") % settings.nixStateDir % tempRootsDir % i.name).str();
debug(format("reading temporary root file `%1%'") % path); debug(format("reading temporary root file `%1%'") % path);
FDPtr fd(new AutoCloseFD(open(path.c_str(), O_RDWR, 0666))); FDPtr fd(new AutoCloseFD(open(path.c_str(), O_RDWR, 0666)));
@ -301,9 +301,8 @@ static void findRoots(StoreAPI & store, const Path & path, Roots & roots)
struct stat st = lstat(path); struct stat st = lstat(path);
if (S_ISDIR(st.st_mode)) { if (S_ISDIR(st.st_mode)) {
Strings names = readDirectory(path); for (auto & i : readDirectory(path))
foreach (Strings::iterator, i, names) findRoots(store, path + "/" + i.name, roots);
findRoots(store, path + "/" + *i, roots);
} }
else if (S_ISLNK(st.st_mode)) { else if (S_ISLNK(st.st_mode)) {
@ -455,7 +454,6 @@ void LocalStore::deletePathRecursive(GCState & state, const Path & path)
// if the path was not valid, need to determine the actual // if the path was not valid, need to determine the actual
// size. // size.
state.bytesInvalidated += size; state.bytesInvalidated += size;
// Mac OS X cannot rename directories if they are read-only.
if (chmod(path.c_str(), st.st_mode | S_IWUSR) == -1) if (chmod(path.c_str(), st.st_mode | S_IWUSR) == -1)
throw SysError(format("making `%1%' writable") % path); throw SysError(format("making `%1%' writable") % path);
Path tmp = state.trashDir + "/" + baseNameOf(path); Path tmp = state.trashDir + "/" + baseNameOf(path);
@ -655,7 +653,7 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results)
/* After this point the set of roots or temporary roots cannot /* After this point the set of roots or temporary roots cannot
increase, since we hold locks on everything. So everything increase, since we hold locks on everything. So everything
that is not reachable from `roots'. */ that is not reachable from `roots' is garbage. */
if (state.shouldDelete) { if (state.shouldDelete) {
if (pathExists(state.trashDir)) deleteGarbage(state, state.trashDir); if (pathExists(state.trashDir)) deleteGarbage(state, state.trashDir);

View file

@ -593,9 +593,9 @@ static void canonicalisePathMetaData_(const Path & path, uid_t fromUid, InodesSe
} }
if (S_ISDIR(st.st_mode)) { if (S_ISDIR(st.st_mode)) {
Strings names = readDirectory(path); DirEntries entries = readDirectory(path);
foreach (Strings::iterator, i, names) for (auto & i : entries)
canonicalisePathMetaData_(path + "/" + *i, fromUid, inodesSeen); canonicalisePathMetaData_(path + "/" + i.name, fromUid, inodesSeen);
} }
} }
@ -1730,8 +1730,8 @@ bool LocalStore::verifyStore(bool checkContents, bool repair)
/* Acquire the global GC lock to prevent a garbage collection. */ /* Acquire the global GC lock to prevent a garbage collection. */
AutoCloseFD fdGCLock = openGCLock(ltWrite); AutoCloseFD fdGCLock = openGCLock(ltWrite);
Paths entries = readDirectory(settings.nixStore); PathSet store;
PathSet store(entries.begin(), entries.end()); for (auto & i : readDirectory(settings.nixStore)) store.insert(i.name);
/* Check whether all valid paths actually exist. */ /* Check whether all valid paths actually exist. */
printMsg(lvlInfo, "checking path existence..."); printMsg(lvlInfo, "checking path existence...");
@ -1881,9 +1881,8 @@ void LocalStore::markContentsGood(const Path & path)
PathSet LocalStore::queryValidPathsOld() PathSet LocalStore::queryValidPathsOld()
{ {
PathSet paths; PathSet paths;
Strings entries = readDirectory(settings.nixDBPath + "/info"); for (auto & i : readDirectory(settings.nixDBPath + "/info"))
foreach (Strings::iterator, i, entries) if (i.name.at(0) != '.') paths.insert(settings.nixStore + "/" + i.name);
if (i->at(0) != '.') paths.insert(settings.nixStore + "/" + *i);
return paths; return paths;
} }
@ -1970,9 +1969,8 @@ static void makeMutable(const Path & path)
if (!S_ISDIR(st.st_mode) && !S_ISREG(st.st_mode)) return; if (!S_ISDIR(st.st_mode) && !S_ISREG(st.st_mode)) return;
if (S_ISDIR(st.st_mode)) { if (S_ISDIR(st.st_mode)) {
Strings names = readDirectory(path); for (auto & i : readDirectory(path))
foreach (Strings::iterator, i, names) makeMutable(path + "/" + i.name);
makeMutable(path + "/" + *i);
} }
/* The O_NOFOLLOW is important to prevent us from changing the /* The O_NOFOLLOW is important to prevent us from changing the

View file

@ -83,22 +83,21 @@ static void dump(const Path & path, Sink & sink, PathFilter & filter)
/* If we're on a case-insensitive system like Mac OS X, undo /* If we're on a case-insensitive system like Mac OS X, undo
the case hack applied by restorePath(). */ the case hack applied by restorePath(). */
Strings names = readDirectory(path);
std::map<string, string> unhacked; std::map<string, string> unhacked;
for (auto & i : names) for (auto & i : readDirectory(path))
if (useCaseHack) { if (useCaseHack) {
string name(i); string name(i.name);
size_t pos = i.find(caseHackSuffix); size_t pos = i.name.find(caseHackSuffix);
if (pos != string::npos) { if (pos != string::npos) {
printMsg(lvlDebug, format("removing case hack suffix from `%1%'") % (path + "/" + i)); printMsg(lvlDebug, format("removing case hack suffix from `%1%'") % (path + "/" + i.name));
name.erase(pos); name.erase(pos);
} }
if (unhacked.find(name) != unhacked.end()) if (unhacked.find(name) != unhacked.end())
throw Error(format("file name collision in between `%1%' and `%2%'") throw Error(format("file name collision in between `%1%' and `%2%'")
% (path + "/" + unhacked[name]) % (path + "/" + i)); % (path + "/" + unhacked[name]) % (path + "/" + i.name));
unhacked[name] = i; unhacked[name] = i.name;
} else } else
unhacked[i] = i; unhacked[i.name] = i.name;
for (auto & i : unhacked) for (auto & i : unhacked)
if (filter(path + "/" + i.first)) { if (filter(path + "/" + i.first)) {

View file

@ -203,9 +203,10 @@ bool isLink(const Path & path)
} }
Strings readDirectory(const Path & path) DirEntries readDirectory(const Path & path)
{ {
Strings names; DirEntries entries;
entries.reserve(64);
AutoCloseDir dir = opendir(path.c_str()); AutoCloseDir dir = opendir(path.c_str());
if (!dir) throw SysError(format("opening directory `%1%'") % path); if (!dir) throw SysError(format("opening directory `%1%'") % path);
@ -215,11 +216,11 @@ Strings readDirectory(const Path & path)
checkInterrupt(); checkInterrupt();
string name = dirent->d_name; string name = dirent->d_name;
if (name == "." || name == "..") continue; if (name == "." || name == "..") continue;
names.push_back(name); entries.emplace_back(DirEntry({ name, dirent->d_ino, dirent->d_type }));
} }
if (errno) throw SysError(format("reading directory `%1%'") % path); if (errno) throw SysError(format("reading directory `%1%'") % path);
return names; return entries;
} }
@ -294,16 +295,14 @@ static void _deletePath(const Path & path, unsigned long long & bytesFreed)
bytesFreed += st.st_blocks * 512; bytesFreed += st.st_blocks * 512;
if (S_ISDIR(st.st_mode)) { if (S_ISDIR(st.st_mode)) {
Strings names = readDirectory(path);
/* Make the directory writable. */ /* Make the directory writable. */
if (!(st.st_mode & S_IWUSR)) { if (!(st.st_mode & S_IWUSR)) {
if (chmod(path.c_str(), st.st_mode | S_IWUSR) == -1) if (chmod(path.c_str(), st.st_mode | S_IWUSR) == -1)
throw SysError(format("making `%1%' writable") % path); throw SysError(format("making `%1%' writable") % path);
} }
for (Strings::iterator i = names.begin(); i != names.end(); ++i) for (auto & i : readDirectory(path))
_deletePath(path + "/" + *i, bytesFreed); _deletePath(path + "/" + i.name, bytesFreed);
} }
if (remove(path.c_str()) == -1) if (remove(path.c_str()) == -1)

View file

@ -64,7 +64,16 @@ bool isLink(const Path & path);
/* Read the contents of a directory. The entries `.' and `..' are /* Read the contents of a directory. The entries `.' and `..' are
removed. */ removed. */
Strings readDirectory(const Path & path); struct DirEntry
{
string name;
ino_t ino;
unsigned char type; // one of DT_*
};
typedef vector<DirEntry> DirEntries;
DirEntries readDirectory(const Path & path);
/* Read the contents of a file into a string. */ /* Read the contents of a file into a string. */
string readFile(int fd); string readFile(int fd);

View file

@ -106,16 +106,16 @@ static bool isNixExpr(const Path & path, struct stat & st)
static void getAllExprs(EvalState & state, static void getAllExprs(EvalState & state,
const Path & path, StringSet & attrs, Value & v) const Path & path, StringSet & attrs, Value & v)
{ {
Strings names = readDirectory(path); StringSet namesSorted;
StringSet namesSorted(names.begin(), names.end()); for (auto & i : readDirectory(path)) namesSorted.insert(i.name);
foreach (StringSet::iterator, i, namesSorted) { for (auto & i : namesSorted) {
/* Ignore the manifest.nix used by profiles. This is /* Ignore the manifest.nix used by profiles. This is
necessary to prevent it from showing up in channels (which necessary to prevent it from showing up in channels (which
are implemented using profiles). */ are implemented using profiles). */
if (*i == "manifest.nix") continue; if (i == "manifest.nix") continue;
Path path2 = path + "/" + *i; Path path2 = path + "/" + i;
struct stat st; struct stat st;
if (stat(path2.c_str(), &st) == -1) if (stat(path2.c_str(), &st) == -1)
@ -126,7 +126,7 @@ static void getAllExprs(EvalState & state,
otherwise the attribute cannot be selected with the otherwise the attribute cannot be selected with the
`-A' option. Useful if you want to stick a Nix `-A' option. Useful if you want to stick a Nix
expression directly in ~/.nix-defexpr. */ expression directly in ~/.nix-defexpr. */
string attrName = *i; string attrName = i;
if (hasSuffix(attrName, ".nix")) if (hasSuffix(attrName, ".nix"))
attrName = string(attrName, 0, attrName.size() - 4); attrName = string(attrName, 0, attrName.size() - 4);
if (attrs.find(attrName) != attrs.end()) { if (attrs.find(attrName) != attrs.end()) {

View file

@ -42,12 +42,11 @@ Generations findGenerations(Path profile, int & curGen)
Path profileDir = dirOf(profile); Path profileDir = dirOf(profile);
string profileName = baseNameOf(profile); string profileName = baseNameOf(profile);
Strings names = readDirectory(profileDir); for (auto & i : readDirectory(profileDir)) {
for (Strings::iterator i = names.begin(); i != names.end(); ++i) {
int n; int n;
if ((n = parseName(profileName, *i)) != -1) { if ((n = parseName(profileName, i.name)) != -1) {
Generation gen; Generation gen;
gen.path = profileDir + "/" + *i; gen.path = profileDir + "/" + i.name;
gen.number = n; gen.number = n;
struct stat st; struct stat st;
if (lstat(gen.path.c_str(), &st) != 0) if (lstat(gen.path.c_str(), &st) != 0)