forked from lix-project/lix
* Some wrapper classes to ensure that file descriptors / directory
handles are closed when they go out of scope.
This commit is contained in:
parent
c62433751d
commit
4a8948b7a6
|
@ -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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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)) {
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -119,16 +119,16 @@ void deletePath(const Path & path)
|
||||||
if (S_ISDIR(st.st_mode)) {
|
if (S_ISDIR(st.st_mode)) {
|
||||||
Strings names;
|
Strings names;
|
||||||
|
|
||||||
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)) {
|
||||||
string name = dirent->d_name;
|
string name = dirent->d_name;
|
||||||
if (name == "." || name == "..") continue;
|
if (name == "." || name == "..") continue;
|
||||||
names.push_back(name);
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
Loading…
Reference in a new issue