summaryrefslogtreecommitdiff
path: root/cpp/src/IceUtil/FileUtil.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'cpp/src/IceUtil/FileUtil.cpp')
-rw-r--r--cpp/src/IceUtil/FileUtil.cpp536
1 files changed, 536 insertions, 0 deletions
diff --git a/cpp/src/IceUtil/FileUtil.cpp b/cpp/src/IceUtil/FileUtil.cpp
new file mode 100644
index 00000000000..1c1b9749301
--- /dev/null
+++ b/cpp/src/IceUtil/FileUtil.cpp
@@ -0,0 +1,536 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2011 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+#include <IceUtil/DisableWarnings.h>
+#include <IceUtil/FileUtil.h>
+#include <IceUtil/Unicode.h>
+#include <IceUtil/Exception.h>
+#include <climits>
+#include <string.h>
+
+#ifdef _WIN32
+# include <process.h>
+#endif
+
+#ifdef _WIN32
+# include <io.h>
+#endif
+
+#ifdef __BCPLUSPLUS__
+# include <dir.h>
+#endif
+
+using namespace std;
+
+//
+// Determine if path is an absolute path
+//
+bool
+IceUtilInternal::isAbsolutePath(const string& path)
+{
+ size_t i = 0;
+ size_t size = path.size();
+
+ // Skip whitespace
+ while(i < size && isspace(static_cast<unsigned char>(path[i])))
+ {
+ ++i;
+ }
+
+#ifdef _WIN32
+ // We need at least 3 non whitespace character to have
+ // and absolute path
+ if(i + 3 > size)
+ {
+ return false;
+ }
+
+ // Check for X:\ path ('\' may have been converted to '/')
+ if((path[i] >= 'A' && path[i] <= 'Z') || (path[i] >= 'a' && path[i] <= 'z'))
+ {
+ return path[i + 1] == ':' && (path[i + 2] == '\\' || path[i + 2] == '/');
+ }
+
+ // Check for UNC path
+ return (path[i] == '\\' && path[i + 1] == '\\') || path[i] == '/';
+#else
+ if(i >= size)
+ {
+ return false;
+ }
+
+ return path[i] == '/';
+#endif
+}
+
+//
+// Determine if a directory exists.
+//
+bool
+IceUtilInternal::directoryExists(const string& path)
+{
+ IceUtilInternal::structstat st;
+ if(IceUtilInternal::stat(path, &st) != 0 || !S_ISDIR(st.st_mode))
+ {
+ return false;
+ }
+ return true;
+}
+
+//
+// Determine if a regular file exists.
+//
+bool
+IceUtilInternal::fileExists(const string& path)
+{
+ IceUtilInternal::structstat st;
+ if(IceUtilInternal::stat(path, &st) != 0 || !S_ISREG(st.st_mode))
+ {
+ return false;
+ }
+ return true;
+}
+
+#ifdef _WIN32
+
+//
+// Stat
+//
+int
+IceUtilInternal::stat(const string& path, structstat* buffer)
+{
+ return _wstat(IceUtil::stringToWstring(path).c_str(), buffer);
+}
+
+int
+IceUtilInternal::remove(const string& path)
+{
+ return ::_wremove(IceUtil::stringToWstring(path).c_str());
+}
+
+int
+IceUtilInternal::rename(const string& from, const string& to)
+{
+ return ::_wrename(IceUtil::stringToWstring(from).c_str(), IceUtil::stringToWstring(to).c_str());
+}
+
+int
+IceUtilInternal::rmdir(const string& path)
+{
+ return ::_wrmdir(IceUtil::stringToWstring(path).c_str());
+}
+
+int
+IceUtilInternal::mkdir(const string& path, int)
+{
+ return ::_wmkdir(IceUtil::stringToWstring(path).c_str());
+}
+
+FILE*
+IceUtilInternal::fopen(const string& path, const string& mode)
+{
+ return ::_wfopen(IceUtil::stringToWstring(path).c_str(), IceUtil::stringToWstring(mode).c_str());
+}
+
+int
+IceUtilInternal::open(const string& path, int flags)
+{
+ if(flags & _O_CREAT)
+ {
+ return ::_wopen(IceUtil::stringToWstring(path).c_str(), flags, _S_IREAD | _S_IWRITE);
+ }
+ else
+ {
+ return ::_wopen(IceUtil::stringToWstring(path).c_str(), flags);
+ }
+}
+
+int
+IceUtilInternal::getcwd(string& cwd)
+{
+ wchar_t cwdbuf[_MAX_PATH];
+ if(_wgetcwd(cwdbuf, _MAX_PATH) == NULL)
+ {
+ return -1;
+ }
+ cwd = IceUtil::wstringToString(cwdbuf);
+ return 0;
+}
+
+int
+IceUtilInternal::unlink(const string& path)
+{
+ return _wunlink(IceUtil::stringToWstring(path).c_str());
+}
+
+int
+IceUtilInternal::close(int fd)
+{
+#if defined(_MSC_VER) && (_MSC_VER >= 1400)
+ return _close(fd);
+#else
+ return ::close(fd);
+#endif
+}
+
+IceUtilInternal::FileLock::FileLock(const std::string& path) :
+ _fd(INVALID_HANDLE_VALUE),
+ _path(path)
+{
+ _fd = ::CreateFileW(IceUtil::stringToWstring(path).c_str(), GENERIC_WRITE, 0, NULL,
+ OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
+ _path = path;
+
+ if(_fd == INVALID_HANDLE_VALUE)
+ {
+ throw IceUtil::FileLockException(__FILE__, __LINE__, GetLastError(), _path);
+ }
+
+ if(::LockFile(_fd, 0, 0, 0, 0) == 0)
+ {
+ ::CloseHandle(_fd);
+ throw IceUtil::FileLockException(__FILE__, __LINE__, GetLastError(), _path);
+ }
+ //
+ // In Windows implementation we don't write the process pid to the file, as is
+ // not posible to read the file from other process while it is locked here.
+ //
+}
+
+IceUtilInternal::FileLock::~FileLock()
+{
+ assert(_fd != INVALID_HANDLE_VALUE);
+ CloseHandle(_fd);
+ unlink(_path);
+}
+
+#ifdef _STLP_BEGIN_NAMESPACE
+namespace
+{
+int
+toFileFlags(ios_base::openmode mode)
+{
+ int flags = 0;
+ if(mode & ios_base::app)
+ {
+ flags |= _O_APPEND;
+ }
+ if(mode & ios_base::trunc)
+ {
+ flags |= _O_TRUNC;
+ }
+ if(mode & ios_base::binary)
+ {
+ flags |= _O_BINARY;
+ }
+ if((mode & ios_base::in) && !(mode & ios_base::out))
+ {
+ flags |= _O_RDONLY;
+ }
+ else if((mode & ios_base::out) && !(mode & ios_base::in))
+ {
+ flags |= _O_WRONLY | _O_CREAT;
+ }
+ else
+ {
+ flags |= _O_RDWR;
+ if(mode & ios_base::trunc)
+ {
+ flags |= _O_CREAT;
+ }
+ }
+ return flags;
+}
+}
+#endif
+
+IceUtilInternal::ifstream::ifstream()
+#ifdef _STLP_BEGIN_NAMESPACE
+ : _fd(-1)
+#endif
+{
+}
+
+#ifdef _STLP_BEGIN_NAMESPACE
+
+IceUtilInternal::ifstream::ifstream(const string& path, ios_base::openmode mode) : _fd(-1)
+{
+ open(path, mode);
+}
+
+IceUtilInternal::ifstream::~ifstream()
+{
+ close();
+}
+
+void
+IceUtilInternal::ifstream::close()
+{
+ if(!rdbuf()->close())
+ {
+ setstate(ios_base::failbit);
+ }
+ if(_fd >= 0)
+ {
+ _close(_fd);
+ }
+}
+
+void
+IceUtilInternal::ifstream::open(const string& path, ios_base::openmode mode)
+{
+ mode |= ifstream::in;
+ _fd = IceUtilInternal::open(path, toFileFlags(mode));
+ if(_fd < 0 || !rdbuf()->open(_fd, mode))
+ {
+ setstate(ios_base::failbit);
+ }
+ if(mode & (ios_base::ate || ios_base::app))
+ {
+ seekg(ios_base::end);
+ }
+}
+
+#else
+
+IceUtilInternal::ifstream::ifstream(const string& path, ios_base::openmode mode) : std::ifstream(IceUtil::stringToWstring(path).c_str(), mode)
+{
+}
+
+void
+IceUtilInternal::ifstream::open(const string& path, ios_base::openmode mode)
+{
+ std::ifstream::open(IceUtil::stringToWstring(path).c_str(), mode);
+}
+
+#endif
+
+IceUtilInternal::ofstream::ofstream()
+#ifdef _STLP_BEGIN_NAMESPACE
+ : _fd(-1)
+#endif
+{
+}
+
+#ifdef _STLP_BEGIN_NAMESPACE
+
+IceUtilInternal::ofstream::ofstream(const string& path, ios_base::openmode mode) : _fd(-1)
+{
+ open(path, mode);
+}
+
+IceUtilInternal::ofstream::~ofstream()
+{
+ close();
+}
+
+void
+IceUtilInternal::ofstream::close()
+{
+ if(!rdbuf()->close())
+ {
+ setstate(ios_base::failbit);
+ }
+ if(_fd >= 0)
+ {
+ _close(_fd);
+ }
+}
+
+void
+IceUtilInternal::ofstream::open(const string& path, ios_base::openmode mode)
+{
+ mode |= ofstream::out;
+ _fd = IceUtilInternal::open(path, toFileFlags(mode));
+ if(_fd < 0 || !rdbuf()->open(_fd, mode))
+ {
+ setstate(ios_base::failbit);
+ }
+ if(mode & (ios_base::ate || ios_base::app))
+ {
+ seekp(ios_base::end);
+ }
+}
+
+#else
+
+IceUtilInternal::ofstream::ofstream(const string& path, ios_base::openmode mode) : std::ofstream(IceUtil::stringToWstring(path).c_str(), mode)
+{
+}
+
+void
+IceUtilInternal::ofstream::open(const string& path, ios_base::openmode mode)
+{
+ std::ofstream::open(IceUtil::stringToWstring(path).c_str(), mode);
+}
+
+#endif
+
+#else
+
+//
+// Stat
+//
+int
+IceUtilInternal::stat(const string& path, structstat* buffer)
+{
+ return ::stat(path.c_str(), buffer);
+}
+
+int
+IceUtilInternal::remove(const string& path)
+{
+ return ::remove(path.c_str());
+}
+
+int
+IceUtilInternal::rename(const string& from, const string& to)
+{
+ return ::rename(from.c_str(), to.c_str());
+}
+
+int
+IceUtilInternal::rmdir(const string& path)
+{
+ return ::rmdir(path.c_str());
+}
+
+int
+IceUtilInternal::mkdir(const string& path, int perm)
+{
+ return ::mkdir(path.c_str(), perm);
+}
+
+FILE*
+IceUtilInternal::fopen(const string& path, const string& mode)
+{
+ return ::fopen(path.c_str(), mode.c_str());
+}
+
+int
+IceUtilInternal::open(const string& path, int flags)
+{
+ if(flags & O_CREAT)
+ {
+ // By default, create with rw-rw-rw- modified by the user's umask (same as fopen).
+ return ::open(path.c_str(), flags, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
+ }
+ else
+ {
+ return ::open(path.c_str(), flags);
+ }
+}
+
+int
+IceUtilInternal::getcwd(string& cwd)
+{
+ char cwdbuf[PATH_MAX];
+ if(::getcwd(cwdbuf, PATH_MAX) == NULL)
+ {
+ return -1;
+ }
+ cwd = cwdbuf;
+ return 0;
+}
+
+int
+IceUtilInternal::unlink(const string& path)
+{
+ return ::unlink(path.c_str());
+}
+
+int
+IceUtilInternal::close(int fd)
+{
+ return ::close(fd);
+}
+
+IceUtilInternal::FileLock::FileLock(const std::string& path) :
+ _fd(-1),
+ _path(path)
+{
+ _fd = ::open(path.c_str(), O_RDWR | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
+ if(_fd < 0)
+ {
+ throw IceUtil::FileLockException(__FILE__, __LINE__, errno, _path);
+ }
+
+ struct ::flock lock;
+ lock.l_type = F_WRLCK; // Write lock
+ lock.l_whence = SEEK_SET; // Begining of file
+ lock.l_start = 0;
+ lock.l_len = 0;
+
+ //
+ // F_SETLK tells fcntl to not block if it cannot
+ // acquire the lock, if the lock cannot be acquired
+ // it returns -1 without wait.
+ //
+ if(::fcntl(_fd, F_SETLK, &lock) == -1)
+ {
+ IceUtil::FileLockException ex(__FILE__, __LINE__, errno, _path);
+ close(_fd);
+ throw ex;
+ }
+
+ //
+ // If there is an error after here, we close the fd,
+ // to release the lock.
+ //
+
+ //
+ // Now that we have acquire an excluxive write lock,
+ // write the process pid there.
+ //
+ ostringstream os;
+ os << getpid();
+
+ if(write(_fd, os.str().c_str(), os.str().size()) == -1)
+ {
+ IceUtil::FileLockException ex(__FILE__, __LINE__, errno, _path);
+ close(_fd);
+ throw ex;
+ }
+}
+
+IceUtilInternal::FileLock::~FileLock()
+{
+ assert(_fd > -1);
+ unlink(_path);
+}
+
+IceUtilInternal::ifstream::ifstream()
+{
+}
+
+IceUtilInternal::ifstream::ifstream(const string& path, ios_base::openmode mode) : std::ifstream(path.c_str(), mode)
+{
+}
+
+void
+IceUtilInternal::ifstream::open(const string& path, ios_base::openmode mode)
+{
+ std::ifstream::open(path.c_str(), mode);
+}
+
+IceUtilInternal::ofstream::ofstream()
+{
+}
+
+IceUtilInternal::ofstream::ofstream(const string& path, ios_base::openmode mode) : std::ofstream(path.c_str(), mode)
+{
+}
+
+void
+IceUtilInternal::ofstream::open(const string& path, ios_base::openmode mode)
+{
+ std::ofstream::open(path.c_str(), mode);
+}
+
+#endif