// \file filesystem.cpp // // Copyright (C) 2014 MicroNeil Research Corporation. // // This program is part of the MicroNeil Research Open Library Project. For // more information go to http://www.microneil.com/OpenLibrary/index.html // // This program is free software; you can redistribute it and/or modify it // under the terms of the GNU General Public License as published by the // Free Software Foundation; either version 2 of the License, or (at your // option) any later version. // // This program is distributed in the hope that it will be useful, but WITHOUT // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for // more details. // // You should have received a copy of the GNU General Public License along with // this program; if not, write to the Free Software Foundation, Inc., 59 Temple // Place, Suite 330, Boston, MA 02111-1307 USA //============================================================================== #ifdef _WIN32 #include #else #include #include #include #include #endif #include #include #include "filesystem.hpp" namespace CodeDweller { FileReference::FileReference(std::string fileName) : name(fileName), modTimestamp(0), size_bytes(0), fileExists(false), fileIsDirectory(false) { refresh(); } void FileReference::refresh() { reset(); // Load info. struct stat statBuffer; int status = stat(name.c_str(), &statBuffer); if (-1 == status) { // File no longer exists. if (ENOENT == errno) { return; } // Something went wrong. throw std::runtime_error("Error updating status of file \"" + name + "\": " + getErrorText()); } modTimestamp = statBuffer.st_mtime; size_bytes = statBuffer.st_size; fileExists = true; fileIsDirectory = S_ISDIR(statBuffer.st_mode); } void FileReference:: reset() { modTimestamp = 0; size_bytes = 0; fileExists = false; fileIsDirectory = false; path.clear(); } time_t FileReference::ModTimestamp() const { return modTimestamp; } size_t FileReference::Size() const { return size_bytes; } std::string FileReference::FullPath() { if (!path.empty()) { return path; } if (!fileExists) { return ""; } #ifdef _WIN32 // Get the size of the full path name. DWORD nTchars = GetFullPathName(name.c_str(), 0, NULL, NULL); if (0 == nTchars) { throw std::runtime_error("Error getting full path length for \"" + name + "\": " + getErrorText()); } size_t bufSize = nTchars * sizeof(TCHAR); TCHAR fullPath[bufSize]; nTchars = GetFullPathName(name.c_str(), bufSize, fullPath, NULL); if (0 == nTchars) { throw std::runtime_error("Error getting full path for \"" + name + "\": " + getErrorText()); } path.assign(fullPath); #else char *realPath = realpath(name.c_str(), NULL); if (NULL == realPath) { // Nothing to do if the file doesn't exist. if (ENOENT == errno) { reset(); return ""; } // Something went wrong. throw std::runtime_error("Error checking file \"" + name + "\": " + getErrorText()); } path.assign(realPath); free(realPath); #endif return path; } bool FileReference::exists() const { return fileExists; } bool FileReference::isDirectory() const { return fileIsDirectory; } std::string FileReference::getErrorText() { #ifdef _WIN32 LPVOID winMsgBuf; DWORD lastError = GetLastError(); FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, lastError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (char *) &winMsgBuf, 0, NULL ); std::string errMsg((char *) winMsgBuf); LocalFree(winMsgBuf); return errMsg; #else return strerror(errno); #endif } }