Back to index

nordugrid-arc-nox  1.1.0~rc6
MkDirRecursive.cpp
Go to the documentation of this file.
00001 // -*- indent-tabs-mode: nil -*-
00002 
00003 #ifdef HAVE_CONFIG_H
00004 #include <config.h>
00005 #endif
00006 
00007 #ifdef WIN32
00008 #include <arc/win32.h>
00009 #endif
00010 
00011 #include <cstdio>
00012 #include <cstdlib>
00013 #include <cstring>
00014 // NOTE: On Solaris errno is not working properly if cerrno is included first
00015 #include <cerrno>
00016 
00017 #include <iostream>
00018 
00019 #include <sys/stat.h>
00020 #include <sys/types.h>
00021 #include <unistd.h>
00022 
00023 #include <glibmm.h>
00024 
00025 #include <arc/data/MkDirRecursive.h>
00026 
00027 static int mkdir_force(const char *path, mode_t mode);
00028 
00029 // TODO: proper solution for windows
00030 int mkdir_recursive(const std::string& base_path, const std::string& path,
00031                     mode_t mode, const Arc::User& user) {
00032   std::string name = Glib::build_filename(base_path,path);
00033   std::string::size_type name_start = base_path.length();
00034   std::string::size_type name_end = name.length();
00035 #ifdef WIN32
00036   // Skip disk:/ part of path if exists
00037   if(Glib::path_is_absolute(name)) {
00038     name_start = name_end - Glib::path_skip_root(name).length();
00039   }  
00040 #endif
00041   /* go down */
00042   for (;;) {
00043     if ((mkdir_force(name.substr(0, name_end).c_str(), mode) == 0) ||
00044         (errno == EEXIST)) {
00045       if (errno != EEXIST)
00046         (lchown(name.substr(0, name_end).c_str(), user.get_uid(),
00047                 user.get_gid()) != 0);
00048       /* go up */
00049       for (;;) {
00050         if (name_end >= name.length())
00051           return 0;
00052         name_end = name.find(G_DIR_SEPARATOR, name_end + 1);
00053         if (mkdir(name.substr(0, name_end).c_str(), mode) != 0) {
00054           if (errno == EEXIST)
00055             continue;
00056           return -1;
00057         }
00058         chmod(name.substr(0, name_end).c_str(), mode);
00059         (lchown(name.substr(0, name_end).c_str(), user.get_uid(),
00060                 user.get_gid()) != 0);
00061       }
00062     }
00063     /* if(errno == EEXIST) { free(name); errno=EEXIST; return -1; } */
00064     if ((name_end = name.rfind(G_DIR_SEPARATOR, name_end - 1)) ==
00065         std::string::npos)
00066       break;
00067     if (name_end == name_start)
00068       break;
00069   }
00070   return -1;
00071 }
00072 
00073 int mkdir_force(const char *path, mode_t mode) {
00074   struct stat st;
00075   int r;
00076   if (stat(path, &st) != 0) {
00077     r = mkdir(path, mode);
00078     if (r == 0)
00079       (void)chmod(path, mode);
00080     return r;
00081   }
00082   if (S_ISDIR(st.st_mode)) { /* simulate error */
00083     r = mkdir(path, mode);
00084     if (r == 0)
00085       (void)chmod(path, mode);
00086     return r;
00087   }
00088   if (remove(path) != 0)
00089     return -1;
00090   r = mkdir(path, mode);
00091   if (r == 0)
00092     (void)chmod(path, mode);
00093   return r;
00094 }