From 4a8948b7a60e751dd809f279f1baa434ea09a4d3 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 22 Oct 2003 10:48:22 +0000 Subject: [PATCH] * Some wrapper classes to ensure that file descriptors / directory handles are closed when they go out of scope. --- src/libnix/archive.cc | 12 ++---- src/libnix/exec.cc | 25 ----------- src/libnix/references.cc | 8 +--- src/libnix/store.cc | 4 +- src/libnix/util.cc | 93 ++++++++++++++++++++++++++++++++++------ src/libnix/util.hh | 37 ++++++++++++++++ 6 files changed, 123 insertions(+), 56 deletions(-) diff --git a/src/libnix/archive.cc b/src/libnix/archive.cc index 9039ad7db..ed57df4c9 100644 --- a/src/libnix/archive.cc +++ b/src/libnix/archive.cc @@ -51,7 +51,7 @@ static void dump(const string & path, DumpSink & sink); static void dumpEntries(const Path & path, DumpSink & sink) { - DIR * dir = opendir(path.c_str()); + AutoCloseDir dir = opendir(path.c_str()); if (!dir) throw SysError("opening directory " + path); vector names; @@ -77,8 +77,6 @@ static void dumpEntries(const Path & path, DumpSink & sink) dump(path + "/" + *it, sink); writeString(")", sink); } - - closedir(dir); /* !!! close on exception */ } @@ -88,7 +86,7 @@ static void dumpContents(const Path & path, unsigned int size, writeString("contents", sink); writeInt(size, sink); - int fd = open(path.c_str(), O_RDONLY); + AutoCloseFD fd = open(path.c_str(), O_RDONLY); if (fd == -1) throw SysError(format("opening file `%1%'") % path); unsigned char buf[65536]; @@ -105,8 +103,6 @@ static void dumpContents(const Path & path, unsigned int size, throw SysError("file changed while reading it: " + path); writePadding(size, sink); - - close(fd); /* !!! close on exception */ } @@ -262,7 +258,7 @@ static void restore(const Path & path, RestoreSource & source) if (s != "(") throw badArchive("expected open tag"); enum { tpUnknown, tpRegular, tpDirectory, tpSymlink } type = tpUnknown; - int fd = -1; /* !!! close on exception */ + AutoCloseFD fd; while (1) { s = readString(source); @@ -326,8 +322,6 @@ static void restore(const Path & path, RestoreSource & source) } } - - if (fd != -1) close(fd); } diff --git a/src/libnix/exec.cc b/src/libnix/exec.cc index 2e092b2e0..a51b605d8 100644 --- a/src/libnix/exec.cc +++ b/src/libnix/exec.cc @@ -11,29 +11,6 @@ #include "globals.hh" -class AutoDelete -{ - string path; - bool del; -public: - - AutoDelete(const string & p) : path(p) - { - del = true; - } - - ~AutoDelete() - { - if (del) deletePath(path); - } - - void cancel() - { - del = false; - } -}; - - static string pathNullDevice = "/dev/null"; @@ -140,5 +117,3 @@ void runProgram(const string & program, throw Error("unable to build package"); } } - - diff --git a/src/libnix/references.cc b/src/libnix/references.cc index be432665b..ab743f76d 100644 --- a/src/libnix/references.cc +++ b/src/libnix/references.cc @@ -36,7 +36,7 @@ void checkPath(const string & path, throw SysError(format("getting attributes of path `%1%'") % path); if (S_ISDIR(st.st_mode)) { - DIR * dir = opendir(path.c_str()); + AutoCloseDir dir = opendir(path.c_str()); struct dirent * dirent; while (errno = 0, dirent = readdir(dir)) { @@ -45,15 +45,13 @@ void checkPath(const string & path, search(name, ids, seen); checkPath(path + "/" + name, ids, seen); } - - closedir(dir); /* !!! close on exception */ } else if (S_ISREG(st.st_mode)) { debug(format("checking `%1%'") % path); - int fd = open(path.c_str(), O_RDONLY); + AutoCloseFD fd = open(path.c_str(), O_RDONLY); if (fd == -1) throw SysError(format("opening file `%1%'") % path); unsigned char * buf = new unsigned char[st.st_size]; @@ -63,8 +61,6 @@ void checkPath(const string & path, search(string((char *) buf, st.st_size), ids, seen); delete buf; /* !!! autodelete */ - - close(fd); /* !!! close on exception */ } else if (S_ISLNK(st.st_mode)) { diff --git a/src/libnix/store.cc b/src/libnix/store.cc index 2d223313b..c40d9efbe 100644 --- a/src/libnix/store.cc +++ b/src/libnix/store.cc @@ -304,14 +304,12 @@ void addTextToStore(const Path & dstPath, const string & s) /* !!! locking? -> parallel writes are probably idempotent */ - int fd = open(dstPath.c_str(), O_CREAT | O_EXCL | O_WRONLY, 0666); + AutoCloseFD fd = open(dstPath.c_str(), O_CREAT | O_EXCL | O_WRONLY, 0666); if (fd == -1) throw SysError(format("creating store file `%1%'") % dstPath); if (write(fd, s.c_str(), s.size()) != (ssize_t) s.size()) throw SysError(format("writing store file `%1%'") % dstPath); - close(fd); /* !!! close on exception */ - Transaction txn(nixDB); registerValidPath(txn, dstPath); txn.commit(); diff --git a/src/libnix/util.cc b/src/libnix/util.cc index c1d0fedea..016ee991a 100644 --- a/src/libnix/util.cc +++ b/src/libnix/util.cc @@ -118,17 +118,17 @@ void deletePath(const Path & path) if (S_ISDIR(st.st_mode)) { Strings names; + + { + AutoCloseDir dir = opendir(path.c_str()); - DIR * dir = opendir(path.c_str()); - - struct dirent * dirent; - while (errno = 0, dirent = readdir(dir)) { - string name = dirent->d_name; - if (name == "." || name == "..") continue; - names.push_back(name); - } - - closedir(dir); /* !!! close on exception */ + struct dirent * dirent; + while (errno = 0, dirent = readdir(dir)) { + string name = dirent->d_name; + if (name == "." || name == "..") continue; + names.push_back(name); + } + } /* scoped to ensure that dir is closed at this point */ /* Make the directory writable. */ if (!(st.st_mode & S_IWUSR)) { @@ -157,7 +157,7 @@ void makePathReadOnly(const Path & path) } if (S_ISDIR(st.st_mode)) { - DIR * dir = opendir(path.c_str()); + AutoCloseDir dir = opendir(path.c_str()); struct dirent * dirent; while (errno = 0, dirent = readdir(dir)) { @@ -165,8 +165,6 @@ void makePathReadOnly(const Path & path) if (name == "." || name == "..") continue; makePathReadOnly(path + "/" + name); } - - closedir(dir); /* !!! close on exception */ } } @@ -251,3 +249,72 @@ void writeFull(int fd, const unsigned char * buf, size_t count) buf += res; } } + + +AutoDelete::AutoDelete(const string & p) : path(p) +{ + del = true; +} + +AutoDelete::~AutoDelete() +{ + if (del) deletePath(path); +} + +void AutoDelete::cancel() +{ + del = false; +} + + +AutoCloseFD::AutoCloseFD() +{ + fd = -1; +} + +AutoCloseFD::AutoCloseFD(int fd) +{ + this->fd = fd; +} + +AutoCloseFD::~AutoCloseFD() +{ + if (fd != -1) close(fd); +} + +void AutoCloseFD::operator =(int fd) +{ + this->fd = fd; +} + +AutoCloseFD::operator int() +{ + return fd; +} + + +AutoCloseDir::AutoCloseDir() +{ + dir = 0; +} + +AutoCloseDir::AutoCloseDir(DIR * dir) +{ + this->dir = dir; +} + +AutoCloseDir::~AutoCloseDir() +{ + if (dir) closedir(dir); +} + +void AutoCloseDir::operator =(DIR * dir) +{ + this->dir = dir; +} + +AutoCloseDir::operator DIR *() +{ + return dir; +} + diff --git a/src/libnix/util.hh b/src/libnix/util.hh index 016289176..02a9b7fcb 100644 --- a/src/libnix/util.hh +++ b/src/libnix/util.hh @@ -6,6 +6,8 @@ #include #include +#include +#include #include #include @@ -113,4 +115,39 @@ void readFull(int fd, unsigned char * buf, size_t count); void writeFull(int fd, const unsigned char * buf, size_t count); +/* Automatic cleanup of resources. */ + +class AutoDelete +{ + string path; + bool del; +public: + AutoDelete(const string & p); + ~AutoDelete(); + void cancel(); +}; + +class AutoCloseFD +{ + int fd; +public: + AutoCloseFD(); + AutoCloseFD(int fd); + ~AutoCloseFD(); + void operator =(int fd); + operator int(); +}; + +class AutoCloseDir +{ + DIR * dir; +public: + AutoCloseDir(); + AutoCloseDir(DIR * dir); + ~AutoCloseDir(); + void operator =(DIR * dir); + operator DIR *(); +}; + + #endif /* !__UTIL_H */