From b424dbfb066f5f45bba8fcdb7e662dd1c801949c Mon Sep 17 00:00:00 2001 From: =?utf8?q?Franti=C5=A1ek=20Dvo=C5=99=C3=A1k?= Date: Tue, 15 Oct 2013 13:17:00 +0200 Subject: [PATCH] opendir()/readdir() improvements: - detect errors even during readdir() - more debugging to syslog - separate raw opendir() (without additional VFS stuff) - keep black magic code around st_nlink disabled --- src/VfsNs.cpp | 45 +++++++++++++++++++++++++++++++++------------ src/VfsNs.h | 1 + 2 files changed, 34 insertions(+), 12 deletions(-) diff --git a/src/VfsNs.cpp b/src/VfsNs.cpp index 7308c8b..d80d0e1 100644 --- a/src/VfsNs.cpp +++ b/src/VfsNs.cpp @@ -174,14 +174,15 @@ ExtendedStat VfsCatalog::extendedStat(const std::string& path, bool follow) thro meta = vfsExtendedStat(components.back(), path, follow); #if 0 -// FIXME: openDir without permissions check and indirect recursion - // black magic - dmlite tests require proper count in st_nlink + // XXX: black magic + // dmlite tests require proper count in st_nlink, + // but another test requires not changed atime if (S_ISDIR(meta.stat.st_mode)) { Directory *dir; struct dirent *entry; int count = 0; - dir = openDir(path); + dir = vfsOpenDir(path); while ((entry = readDir(dir)) != NULL) { if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) continue; @@ -509,17 +510,12 @@ void VfsCatalog::updateExtendedAttributes(const std::string& path, -Directory* VfsCatalog::openDir(const std::string& path) throw (DmException) +PrivateDir* VfsCatalog::vfsOpenDir(const std::string& path) throw (DmException) { PrivateDir *privateDir; - ExtendedStat meta; privateDir = new PrivateDir(); try { - meta = this->extendedStat(path); - if (checkPermissions(this->secCtx_, meta.acl, meta.stat, S_IREAD) != 0) - vfsThrow(EACCES, "not enough permissions for '%s' to read '%s'", clientName.c_str(), path.c_str()); - privateDir->path = path; privateDir->dir = opendir(path.c_str()); if (privateDir->dir == NULL) @@ -534,10 +530,28 @@ Directory* VfsCatalog::openDir(const std::string& path) throw (DmException) +Directory* VfsCatalog::openDir(const std::string& path) throw (DmException) +{ + PrivateDir *privateDir; + ExtendedStat meta; + + meta = this->extendedStat(path); + if (checkPermissions(this->secCtx_, meta.acl, meta.stat, S_IREAD) != 0) + vfsThrow(EACCES, "not enough permissions for '%s' to read '%s'", clientName.c_str(), path.c_str()); + + privateDir = vfsOpenDir(path); + + syslog(LOG_DEBUG, "%s: directory '%s' opened", __func__, path.c_str()); + return privateDir; +} + + + void VfsCatalog::closeDir(Directory* dir) throw (DmException) { int r; PrivateDir *privateDir = dynamic_cast(dir); + std::string path = privateDir->path; if (privateDir == NULL) throw DmException(DMLITE_SYSERR(EFAULT), @@ -547,6 +561,7 @@ void VfsCatalog::closeDir(Directory* dir) throw (DmException) delete privateDir; wrapCall(r); + syslog(LOG_DEBUG, "%s: directory '%s' closed", __func__, path.c_str()); } @@ -554,12 +569,18 @@ void VfsCatalog::closeDir(Directory* dir) throw (DmException) struct dirent* VfsCatalog::readDir(Directory* dir) throw (DmException) { PrivateDir *privateDir = dynamic_cast(dir); + struct dirent *ent; if (privateDir == NULL) - throw DmException(DMLITE_SYSERR(EFAULT), - "Tried to read a null directory"); + vfsThrow(DMLITE_SYSERR(EFAULT), "Tried to read a null directory"); + + errno = 0; + ent = readdir(privateDir->dir); + if (!ent && errno) + vfsThrow(errno, "readdir() on '%s' failed", privateDir->path.c_str()); - return static_cast(readdir(privateDir->dir)); + syslog(LOG_DEBUG, "%s: result %s", __func__, ent ? ent->d_name : "(null)"); + return static_cast(ent); } diff --git a/src/VfsNs.h b/src/VfsNs.h index 3d8c72b..11491de 100644 --- a/src/VfsNs.h +++ b/src/VfsNs.h @@ -102,6 +102,7 @@ namespace dmlite { ExtendedStat getParent(const std::string& path, std::string* parentPath, std::string* name) throw (DmException); ExtendedStat vfsExtendedStat(const std::string& name, const std::string& path, bool follow) throw (DmException); + PrivateDir* vfsOpenDir(const std::string& path) throw (DmException); StackInstance* si_; const SecurityContext* secCtx_; -- 1.8.2.3