* Some wrapper classes to ensure that file descriptors / directory

handles are closed when they go out of scope.
This commit is contained in:
Eelco Dolstra 2003-10-22 10:48:22 +00:00
parent c62433751d
commit 4a8948b7a6
6 changed files with 123 additions and 56 deletions

View file

@ -51,7 +51,7 @@ static void dump(const string & path, DumpSink & sink);
static void dumpEntries(const Path & 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); if (!dir) throw SysError("opening directory " + path);
vector<string> names; vector<string> names;
@ -77,8 +77,6 @@ static void dumpEntries(const Path & path, DumpSink & sink)
dump(path + "/" + *it, sink); dump(path + "/" + *it, sink);
writeString(")", sink); writeString(")", sink);
} }
closedir(dir); /* !!! close on exception */
} }
@ -88,7 +86,7 @@ static void dumpContents(const Path & path, unsigned int size,
writeString("contents", sink); writeString("contents", sink);
writeInt(size, 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); if (fd == -1) throw SysError(format("opening file `%1%'") % path);
unsigned char buf[65536]; 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); throw SysError("file changed while reading it: " + path);
writePadding(size, sink); 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"); if (s != "(") throw badArchive("expected open tag");
enum { tpUnknown, tpRegular, tpDirectory, tpSymlink } type = tpUnknown; enum { tpUnknown, tpRegular, tpDirectory, tpSymlink } type = tpUnknown;
int fd = -1; /* !!! close on exception */ AutoCloseFD fd;
while (1) { while (1) {
s = readString(source); s = readString(source);
@ -326,8 +322,6 @@ static void restore(const Path & path, RestoreSource & source)
} }
} }
if (fd != -1) close(fd);
} }

View file

@ -11,29 +11,6 @@
#include "globals.hh" #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"; static string pathNullDevice = "/dev/null";
@ -140,5 +117,3 @@ void runProgram(const string & program,
throw Error("unable to build package"); throw Error("unable to build package");
} }
} }

View file

@ -36,7 +36,7 @@ void checkPath(const string & path,
throw SysError(format("getting attributes of path `%1%'") % path); throw SysError(format("getting attributes of path `%1%'") % path);
if (S_ISDIR(st.st_mode)) { if (S_ISDIR(st.st_mode)) {
DIR * dir = opendir(path.c_str()); AutoCloseDir dir = opendir(path.c_str());
struct dirent * dirent; struct dirent * dirent;
while (errno = 0, dirent = readdir(dir)) { while (errno = 0, dirent = readdir(dir)) {
@ -45,15 +45,13 @@ void checkPath(const string & path,
search(name, ids, seen); search(name, ids, seen);
checkPath(path + "/" + name, ids, seen); checkPath(path + "/" + name, ids, seen);
} }
closedir(dir); /* !!! close on exception */
} }
else if (S_ISREG(st.st_mode)) { else if (S_ISREG(st.st_mode)) {
debug(format("checking `%1%'") % path); 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); if (fd == -1) throw SysError(format("opening file `%1%'") % path);
unsigned char * buf = new unsigned char[st.st_size]; 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); search(string((char *) buf, st.st_size), ids, seen);
delete buf; /* !!! autodelete */ delete buf; /* !!! autodelete */
close(fd); /* !!! close on exception */
} }
else if (S_ISLNK(st.st_mode)) { else if (S_ISLNK(st.st_mode)) {

View file

@ -304,14 +304,12 @@ void addTextToStore(const Path & dstPath, const string & s)
/* !!! locking? -> parallel writes are probably idempotent */ /* !!! 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 (fd == -1) throw SysError(format("creating store file `%1%'") % dstPath);
if (write(fd, s.c_str(), s.size()) != (ssize_t) s.size()) if (write(fd, s.c_str(), s.size()) != (ssize_t) s.size())
throw SysError(format("writing store file `%1%'") % dstPath); throw SysError(format("writing store file `%1%'") % dstPath);
close(fd); /* !!! close on exception */
Transaction txn(nixDB); Transaction txn(nixDB);
registerValidPath(txn, dstPath); registerValidPath(txn, dstPath);
txn.commit(); txn.commit();

View file

@ -118,17 +118,17 @@ void deletePath(const Path & path)
if (S_ISDIR(st.st_mode)) { if (S_ISDIR(st.st_mode)) {
Strings names; Strings names;
{
AutoCloseDir dir = opendir(path.c_str());
DIR * dir = opendir(path.c_str()); struct dirent * dirent;
while (errno = 0, dirent = readdir(dir)) {
struct dirent * dirent; string name = dirent->d_name;
while (errno = 0, dirent = readdir(dir)) { if (name == "." || name == "..") continue;
string name = dirent->d_name; names.push_back(name);
if (name == "." || name == "..") continue; }
names.push_back(name); } /* scoped to ensure that dir is closed at this point */
}
closedir(dir); /* !!! close on exception */
/* Make the directory writable. */ /* Make the directory writable. */
if (!(st.st_mode & S_IWUSR)) { if (!(st.st_mode & S_IWUSR)) {
@ -157,7 +157,7 @@ void makePathReadOnly(const Path & path)
} }
if (S_ISDIR(st.st_mode)) { if (S_ISDIR(st.st_mode)) {
DIR * dir = opendir(path.c_str()); AutoCloseDir dir = opendir(path.c_str());
struct dirent * dirent; struct dirent * dirent;
while (errno = 0, dirent = readdir(dir)) { while (errno = 0, dirent = readdir(dir)) {
@ -165,8 +165,6 @@ void makePathReadOnly(const Path & path)
if (name == "." || name == "..") continue; if (name == "." || name == "..") continue;
makePathReadOnly(path + "/" + name); 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; 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;
}

View file

@ -6,6 +6,8 @@
#include <set> #include <set>
#include <sstream> #include <sstream>
#include <sys/types.h>
#include <dirent.h>
#include <unistd.h> #include <unistd.h>
#include <boost/format.hpp> #include <boost/format.hpp>
@ -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); 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 */ #endif /* !__UTIL_H */