/* * libjingle * Copyright 2004--2006, Google Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include "talk/base/basicdefs.h" #include "talk/base/convert.h" #include "talk/base/pathutils.h" #include "talk/base/fileutils.h" #include "talk/base/stringutils.h" #include "talk/base/stream.h" #include "talk/base/win32filesystem.h" namespace talk_base { bool Win32Filesystem::CreateFolderI(const Pathname &pathname) { int len = pathname.pathname().length(); if ((len <= 0) || (pathname.pathname().c_str()[len-1] != '\\')) { return false; } DWORD res = ::GetFileAttributes(Utf16(pathname.pathname()).AsWz()); if (res != INVALID_FILE_ATTRIBUTES) { // Something exists at this location, check if it is a directory return ((res & FILE_ATTRIBUTE_DIRECTORY) != 0); } else if ((GetLastError() != ERROR_FILE_NOT_FOUND) && (GetLastError() != ERROR_PATH_NOT_FOUND)) { // Unexpected error return false; } // Directory doesn't exist, look up one directory level do { --len; } while ((len > 0) && (pathname.pathname().c_str()[len-1] != '\\')); if (!CreateFolder(std::string(pathname.pathname().c_str(),len))) return false; if (pathname.pathname().c_str()[0] != '\\') { std::string long_path = std::string("\\\\?\\") + pathname.pathname(); return (::CreateDirectory(Utf16(long_path).AsWz(), NULL) != 0); } else { return (::CreateDirectory(Utf16(pathname.pathname()).AsWz(), NULL) != 0); } } FileStream *Win32Filesystem::OpenFileI(const Pathname &filename, const std::string &mode) { talk_base::FileStream *fs = new talk_base::FileStream(); if (fs) fs->Open(filename.pathname().c_str(), mode.c_str()); return fs; } bool Win32Filesystem::DeleteFileI(const Pathname &filename) { LOG(LS_INFO) << "Deleting " << filename.pathname(); if (IsFolder(filename)) { Pathname dir; dir.SetFolder(filename.pathname()); DirectoryIterator di; di.Iterate(dir.pathname()); while(di.Next()) { if (di.Name() == "." || di.Name() == "..") continue; Pathname subdir; subdir.SetFolder(filename.pathname()); subdir.SetFilename(di.Name()); if (!DeleteFile(subdir.pathname())) return false; } std::string no_slash(filename.pathname(), 0, filename.pathname().length()-1); return ::RemoveDirectory(Utf16(no_slash).AsWz()) == 0; } return ::DeleteFile(Utf16(filename.pathname()).AsWz()) == 0; } bool Win32Filesystem::GetTemporaryFolderI(Pathname &pathname, bool create, const std::string *append) { // ASSERT(!g_application_name_.empty()); wchar_t buffer[MAX_PATH + 1]; if (!::GetTempPath(ARRAY_SIZE(buffer), buffer)) return false; if (!::GetLongPathName(buffer, buffer, ARRAY_SIZE(buffer))) return false; size_t len = strlen(buffer); if ((len > 0) && (buffer[len-1] != '\\')) { len += talk_base::strcpyn(buffer + len, ARRAY_SIZE(buffer) - len, L"\\"); } if ((len > 0) && (buffer[len-1] != '\\')) { len += talk_base::strcpyn(buffer + len, ARRAY_SIZE(buffer) - len, L"\\"); } if (len >= ARRAY_SIZE(buffer) - 1) return false; pathname.clear(); pathname.SetFolder(Utf8(buffer).AsSz()); if (append != NULL) pathname.AppendFolder(*append); if (create) CreateFolderI(pathname); return true; } std::string Win32Filesystem::TempFilenameI(const Pathname &dir, const std::string &prefix) { wchar_t filename[MAX_PATH]; if (::GetTempFileName(Utf16(dir.pathname()).AsWz(), Utf16(prefix).AsWz(), 0, filename) == 0) return Utf8(filename).AsString(); return ""; } bool Win32Filesystem::MoveFileI(const Pathname &old_path, const Pathname &new_path) { LOG(LS_INFO) << "Moving " << old_path.pathname() << " to " << new_path.pathname(); if (_wrename(Utf16(old_path.pathname()).AsWz(), Utf16(new_path.pathname()).AsWz()) != 0) { if (errno != EXDEV) { printf("errno: %d\n", errno); return false; } if (!CopyFile(old_path, new_path)) return false; if (!DeleteFile(old_path)) return false; } return true; } bool Win32Filesystem::IsFolderI(const Pathname &path) { WIN32_FILE_ATTRIBUTE_DATA data = {0}; if (0 == ::GetFileAttributesEx(Utf16(path.pathname()).AsWz(), GetFileExInfoStandard, &data)) return false; return (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY; } bool Win32Filesystem::FileExistsI(const Pathname &path) { DWORD res = ::GetFileAttributes(Utf16(path.pathname()).AsWz()); return res != INVALID_FILE_ATTRIBUTES; } bool Win32Filesystem::CopyFileI(const Pathname &old_path, const Pathname &new_path) { return ::CopyFile(Utf16(old_path.pathname()).AsWz(), Utf16(new_path.pathname()).AsWz(), TRUE) == 0; } bool Win32Filesystem::IsTemporaryPathI(const Pathname& pathname) { TCHAR buffer[MAX_PATH + 1]; if (!::GetTempPath(ARRAY_SIZE(buffer), buffer)) return false; if (!::GetLongPathName(buffer, buffer, ARRAY_SIZE(buffer))) return false; return (::strnicmp(Utf16(pathname.pathname()).AsWz(), buffer, strlen(buffer)) == 0); } bool Win32Filesystem::GetFileSizeI(const Pathname &pathname, size_t *size) { WIN32_FILE_ATTRIBUTE_DATA data = {0}; if (::GetFileAttributesEx(Utf16(pathname.pathname()).AsWz(), GetFileExInfoStandard, &data) == 0) return false; *size = data.nFileSizeLow; return true; } }