opendir()/readdir() improvements:
authorFrantišek Dvořák <valtri@civ.zcu.cz>
Tue, 15 Oct 2013 11:17:00 +0000 (13:17 +0200)
committerFrantišek Dvořák <valtri@civ.zcu.cz>
Tue, 15 Oct 2013 11:17:00 +0000 (13:17 +0200)
- 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
src/VfsNs.h

index 7308c8b..d80d0e1 100644 (file)
@@ -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<PrivateDir*>(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<PrivateDir*>(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<struct dirent*>(readdir(privateDir->dir));
+  syslog(LOG_DEBUG, "%s: result %s", __func__, ent ? ent->d_name : "(null)");
+  return static_cast<struct dirent*>(ent);
 }
 
 
index 3d8c72b..11491de 100644 (file)
@@ -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_;