/* * vislib::sys::Path::MakeDirectory */ void vislib::sys::Path::MakeDirectory(const StringA& path) { Stack<StringA> missingParts; StringA firstBuilt; StringA curPath = Resolve(path); while (!File::Exists(curPath)) { StringA::Size pos = curPath.FindLast(SEPARATOR_A); if (pos != StringA::INVALID_POS) { missingParts.Push(curPath.Substring(pos + 1)); if (missingParts.Peek()->IsEmpty()) { // Remove empty directories as the incremental directory // creation later on will fail for these. missingParts.Pop(); } curPath.Truncate(pos); } else { // Problem: No Separators left, but directory still does not exist. #ifdef _WIN32 throw vislib::sys::SystemException(ERROR_INVALID_NAME, __FILE__, __LINE__); #else /* _WIN32 */ throw vislib::sys::SystemException(EINVAL, __FILE__, __LINE__); #endif /* _WIN32 */ } } // curPath exists if (!File::IsDirectory(curPath)) { // the latest existing directory is not a directory (may be a file?) #ifdef _WIN32 throw vislib::sys::SystemException(ERROR_DIRECTORY, __FILE__, __LINE__); #else /* _WIN32 */ throw vislib::sys::SystemException(EEXIST, __FILE__, __LINE__); #endif /* _WIN32 */ } while (!missingParts.IsEmpty()) { curPath += SEPARATOR_A; curPath += missingParts.Pop(); #ifdef _WIN32 if (CreateDirectoryA(curPath, NULL) != 0) { #else /* _WIN32 */ if (mkdir(curPath, S_IRWXG | S_IRWXO | S_IRWXU) == 0) { // TODO: Check #endif /* _WIN32 */ // success, so go on. if (firstBuilt.IsEmpty()) { firstBuilt = curPath; } } else { DWORD errorCode = GetLastError(); try { // failure, so try to remove already created paths and throw exception. DeleteDirectory(firstBuilt, true); } catch(...) { } throw vislib::sys::SystemException(errorCode, __FILE__, __LINE__); } } // we are done! } /* * vislib::sys::Path::MakeDirectory */ void vislib::sys::Path::MakeDirectory(const StringW& path) { #ifdef _WIN32 Stack<StringW> missingParts; StringW firstBuilt; StringW curPath = Resolve(path); while (!File::Exists(curPath)) { StringW::Size pos = curPath.FindLast(SEPARATOR_W); if (pos != StringW::INVALID_POS) { missingParts.Push(curPath.Substring(pos + 1)); if (missingParts.Peek()->IsEmpty()) { // Remove empty directories as the incremental directory // creation later on will fail for these. missingParts.Pop(); } curPath.Truncate(pos); } else { // Problem: No Separators left, but directory still does not exist. throw vislib::sys::SystemException(ERROR_INVALID_NAME, __FILE__, __LINE__); } } // curPath exists if (!File::IsDirectory(curPath)) { // the latest existing directory is not a directory (may be a file?) throw vislib::sys::SystemException(ERROR_DIRECTORY, __FILE__, __LINE__); } while (!missingParts.IsEmpty()) { curPath += SEPARATOR_W; curPath += missingParts.Pop(); if (CreateDirectoryW(curPath, NULL) != 0) { // success, so go on. if (firstBuilt.IsEmpty()) { firstBuilt = curPath; } } else { DWORD errorCode = GetLastError(); try { // failure, so try to remove already created paths and throw exception. DeleteDirectory(firstBuilt, true); } catch(...) { } throw vislib::sys::SystemException(errorCode, __FILE__, __LINE__); } } // we are done! #else /* _WIN32 */ // linux is stupid MakeDirectory(W2A(path)); #endif /* _WIN32 */ }
/* * vislib::sys::Path::Canonicalise */ vislib::StringA vislib::sys::Path::Canonicalise(const StringA& path) { const StringA DOUBLE_SEPARATOR(Path::SEPARATOR_A, 2); #ifdef _WIN32 StringA retval; if (::PathCanonicalizeA(retval.AllocateBuffer(MAX_PATH), path) != TRUE) { throw SystemException(__FILE__, __LINE__); } retval.Replace(DOUBLE_SEPARATOR.PeekBuffer(), SEPARATOR_A); retval.Replace(DOUBLE_SEPARATOR.PeekBuffer(), SEPARATOR_A); /* Ensure that a UNC path remains a UNC path. */ if (path.StartsWith(DOUBLE_SEPARATOR)) { // Note: Double separator replacement above leaves at least one // separator, so we must only prepend one additional one. retval.Prepend(SEPARATOR_A); } return retval; #else /* _WIN32 */ const char *BACK_REF = "/.."; const char *CUR_REF = "/."; // Note: "./" does not work StringA::Size BACK_REF_LEN = ::strlen(BACK_REF); StringA::Size bwRefPos = 0; // Position of back reference. StringA::Size remDirPos = 0; // Position of directory to erase. StringA retval(path); /* Remove backward references, first. */ while ((bwRefPos = retval.Find(BACK_REF)) != StringA::INVALID_POS) { if ((bwRefPos > 0) && (remDirPos = retval.FindLast(SEPARATOR_A, bwRefPos - 1)) != StringA::INVALID_POS) { /* Found inner backward reference, so remove some parts. */ retval.Remove(remDirPos, bwRefPos - remDirPos + BACK_REF_LEN); } else { /* * No other path separator is before this one, so we can remove * everything before 'bwRefPos'. */ retval.Remove(0, bwRefPos + BACK_REF_LEN); } } /* * Remove references to the current directory. This must be done after * removing backward references. */ retval.Remove(CUR_REF); /* Remove odd and even number of repeated path separators. */ retval.Replace(DOUBLE_SEPARATOR.PeekBuffer(), SEPARATOR_A); retval.Replace(DOUBLE_SEPARATOR.PeekBuffer(), SEPARATOR_A); return retval; #endif /* _WIN32 */ }