Fix uploading into subdirectories (mkdir()s moved from PoolHandler to IO Driver)...
authorFrantišek Dvořák <valtri@civ.zcu.cz>
Tue, 15 Oct 2013 11:35:28 +0000 (13:35 +0200)
committerFrantišek Dvořák <valtri@civ.zcu.cz>
Tue, 15 Oct 2013 11:35:28 +0000 (13:35 +0200)
src/VfsDriver.cpp
src/VfsIO.cpp
src/VfsIO.h

index d3a48fd..25700ba 100644 (file)
@@ -210,7 +210,7 @@ Location VfsPoolHandler::whereToWrite(const std::string& sfn) throw (DmException
   Chunk single;
   Url wloc;
   std::vector<std::string> components;
-  std::string path, curdir, parentdir;
+  std::string path, parentdir;
   struct stat fstat;
 
   if (sfn.empty() || sfn[0] != '/') path = "/" + sfn;
@@ -220,29 +220,9 @@ Location VfsPoolHandler::whereToWrite(const std::string& sfn) throw (DmException
   components.pop_back();
   parentdir = Url::joinPath(components);
 
-  //
-  // check the parent directory and try to create subtree if not available
-  //
-  // Catalog checks permissions in all parent directories, so with disk is in
-  // sync with namespace, the creating of subtree should not be needed.
-  //
-  if (stat(getLocalPath(parentdir).c_str(), &fstat) == -1) {
-    components = Url::splitPath(path);
-    curdir = "";
-    for (unsigned int i = 0; i < components.size() - 1; i++) {
-      // the first component always '/', let's use it as separator
-      if (i < 2) curdir += components[i];
-      else curdir = curdir + "/" + components[i];
-      // ignore all errors - we stupidly go from '/' toward deeper levels
-      mkdir(getLocalPath(curdir).c_str(), 0755);
-    }
-
-    // detailed error from stat() only after the attempt for the subtree
-    wrapCall(stat(getLocalPath(curdir).c_str(), &fstat), "parent directory '%s' not available", curdir.c_str());
-  }
-
+  wrapCall(stat(getLocalPath(parentdir).c_str(), &fstat), "parent directory '%s' not available", parentdir.c_str());
   if (!S_ISDIR(fstat.st_mode))
-    vfsThrow(ENOTDIR, "'%s' is not directory", curdir.c_str());
+    vfsThrow(ENOTDIR, "'%s' is not directory", parentdir.c_str());
 
   wloc = Url(path);
 
index 41111b1..60fdf4d 100644 (file)
@@ -1,8 +1,11 @@
 /// @file   VfsIO.cpp
 /// @brief  IO factory.
 /// @author Alejandro Álvarez Ayllón <aalvarez@cern.ch>
-#include <dmlite/cpp/dmlite.h>
+#include <sys/types.h>
+#include <sys/stat.h>
 #include <errno.h>
+#include <unistd.h>
+#include <dmlite/cpp/dmlite.h>
 #include "Vfs.h"
 #include "VfsIO.h"
 
@@ -80,23 +83,45 @@ void VfsIODriver::doneWriting(const Location &loc) throw (DmException)
 
 
 
-VfsIOHandler::VfsIOHandler(const std::string& path, const std::string& prefix,
+VfsIOHandler::VfsIOHandler(const std::string& urlpath, const std::string& prefix,
                            int flags, mode_t mode) throw (DmException):
   eof_(false), pos_(0)
 { 
-  std::string real;
+  std::string path, lpath, parentdir, curdir;
+  std::vector<std::string> components;
+  struct stat fstat;
   
-  if (path.compare(0, 5, "/vfs/") != 0)
-    vfsThrow(EINVAL, "file not on the /vfs/ namespace");
-
   this->prefix_ = prefix;
 
-  real = getLocalPath(path.substr(4));
+  if (urlpath.compare(0, 5, "/vfs/") != 0)
+    vfsThrow(EINVAL, "file not on the /vfs/ namespace");
+
+  path = urlpath.substr(4);
+  components = Url::splitPath(path);
+  components.pop_back();
+  if (components.size() == 1 && components[0] == "/") parentdir = "/";
+  else parentdir = Url::joinPath(components);
+
+  //
+  // check the parent directory and try to create subtree if not available
+  //
+  if (stat(getLocalPath(parentdir).c_str(), &fstat) == -1) {
+    curdir = this->prefix_;
+    for (unsigned int i = 0; i < components.size(); i++) {
+      // the first component always '/', let's use it as separator
+      if (i < 2) curdir += components[i];
+      else curdir = curdir + "/" + components[i];
+      // ignore all errors - just go from "/" toward deeper levels
+      if (mkdir(curdir.c_str(), 0755) == 0)
+        syslog(LOG_DEBUG, "%s: created directory '%s'", __func__, curdir.c_str());
+    }
+  }
+  lpath = getLocalPath(path);
   
-  this->fd_ = ::open(real.c_str(), flags, mode);
-  syslog(LOG_DEBUG, "%s: open('%s', flags=%04X, mode=%04o) = %d", __func__, real.c_str(), flags, mode, this->fd_);
+  this->fd_ = ::open(lpath.c_str(), flags, mode);
+  syslog(LOG_DEBUG, "%s: open('%s', flags=%04X, mode=%04o) = %d", __func__, lpath.c_str(), flags, mode, this->fd_);
   if (this->fd_ == -1)
-    vfsThrowErrno("could not open %s)", path.c_str());
+    vfsThrowErrno("could not open '%s'", lpath.c_str());
 }
 
 
index e8e6d82..eba6eea 100644 (file)
@@ -36,7 +36,7 @@ namespace dmlite {
 
   class VfsIOHandler: public IOHandler {
   public:
-    VfsIOHandler(const std::string& path, const std::string& prefix,
+    VfsIOHandler(const std::string& urlpath, const std::string& prefix,
                  int flags, mode_t mode) throw (DmException);
     ~VfsIOHandler();