diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index f2ad6229c..be045f100 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -18,6 +18,7 @@ include_directories( set(llcommon_SOURCE_FILES aialert.cpp + aifile.cpp aiframetimer.cpp aithreadid.cpp imageids.cpp @@ -108,6 +109,7 @@ set(llcommon_HEADER_FILES CMakeLists.txt aialert.h + aifile.h aiframetimer.h airecursive.h aithreadid.h diff --git a/indra/llcommon/aifile.cpp b/indra/llcommon/aifile.cpp new file mode 100644 index 000000000..4013f3cf7 --- /dev/null +++ b/indra/llcommon/aifile.cpp @@ -0,0 +1,118 @@ +/** + * @file aifile.cpp + * @brief POSIX file operations that throw on error. + * + * Copyright (c) 2013, Aleric Inglewood. + * + * 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, see . + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution. + * + * CHANGELOG + * and additional copyright holders. + * + * 03/11/2013 + * Initial version, written by Aleric Inglewood @ SL + */ + +#include "linden_common.h" +#include "aifile.h" +#include "aialert.h" + +#if LL_WINDOWS +#include +#include // Windows errno +#else +#include +#endif + +AIFile::AIFile(std::string const& filename, char const* accessmode) +{ + mFp = AIFile::fopen(filename, accessmode); +} + +AIFile::~AIFile() +{ + AIFile::close(mFp); +} + +// Like THROW_MALERTE but appends "LLFile::strerr(errn) << " (" << errn << ')'" as argument to replace [ERROR]. +#define THROW_ERROR(...) \ + do { \ + int errn = errno; \ + std::ostringstream error; \ + error << LLFile::strerr(errn) << " (" << errn << ')'; \ + THROW_MALERT_CLASS(AIAlertCode, errn, __VA_ARGS__ ("[ERROR]", error.str())); \ + } while(0) + +//static +void AIFile::mkdir(std::string const& dirname, int perms) +{ + int rc = LLFile::mkdir(dirname, perms); + if (rc < 0 && rc != EEXIST) + { + THROW_ERROR("AIFile_mkdir_Failed_to_create_DIRNAME", AIArgs("[DIRNAME]", dirname)); + } +} + +//static +void AIFile::rmdir(std::string const& dirname) +{ + int rc = LLFile::rmdir(dirname); + if (rc < 0 && rc != ENOENT) + { + THROW_ERROR("AIFile_rmdir_Failed_to_remove_DIRNAME", AIArgs("[DIRNAME]", dirname)); + } +} + +//static +LLFILE* AIFile::fopen(std::string const& filename, const char* mode) +{ + LLFILE* fp = LLFile::fopen(filename, mode); + if (!fp) + { + THROW_ERROR("AIFile_fopen_Failed_to_open_FILENAME", AIArgs("[FILENAME]", filename)); + } + return fp; +} + +//static +void AIFile::close(LLFILE* file) +{ + if (LLFile::close(file) < 0) + { + THROW_ERROR("AIFile_close_Failed_to_close_file", AIArgs); + } +} + +//static +void AIFile::remove(std::string const& filename) +{ + if (LLFile::remove(filename) < 0) + { + THROW_ERROR("AIFile_remove_Failed_to_remove_FILENAME", AIArgs("[FILENAME]", filename)); + } +} + +//static +void AIFile::rename(std::string const& filename, std::string const& newname) +{ + if (LLFile::rename(filename, newname) < 0) + { + THROW_ERROR("AIFile_rename_Failed_to_rename_FILE_to_NEWFILE", AIArgs("[FILE]", filename)("[NEWFILE]", newname)); + } +} + diff --git a/indra/llcommon/aifile.h b/indra/llcommon/aifile.h new file mode 100644 index 000000000..1b110496a --- /dev/null +++ b/indra/llcommon/aifile.h @@ -0,0 +1,59 @@ +/** + * @file aifile.h + * @brief Declaration of AIFile. + * + * Copyright (c) 2013, Aleric Inglewood. + * + * 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, see . + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution. + * + * CHANGELOG + * and additional copyright holders. + * + * 02/11/2013 + * Initial version, written by Aleric Inglewood @ SL + */ + +#ifndef AIFILE_H +#define AIFILE_H + +#include "llfile.h" + +// As LLFile, but throws AIAlert instead of printing a warning. +class LL_COMMON_API AIFile +{ + private: + LLFILE* mFp; + + public: + // Scoped file (exception safe). Throws AIAlertCode with errno on failure. + AIFile(std::string const& filename, char const* accessmode); + ~AIFile(); + + operator LLFILE* () const { return mFp; } + + // All these functions take UTF8 path/filenames. + static LLFILE* fopen(std::string const& filename, char const* accessmode); + static void close(LLFILE* file); + + static void mkdir(std::string const& dirname, int perms = 0700); // Does NOT throw when dirname already exists. + static void rmdir(std::string const& dirname); // Does NOT throw when dirname does not exist. + static void remove(std::string const& filename); // Does NOT throw when filename does not exist. + static void rename(std::string const& filename, std::string const& newname); +}; + +#endif // AIFILE_H diff --git a/indra/newview/skins/default/xui/en-us/strings.xml b/indra/newview/skins/default/xui/en-us/strings.xml index b65877527..980bbcaa1 100644 --- a/indra/newview/skins/default/xui/en-us/strings.xml +++ b/indra/newview/skins/default/xui/en-us/strings.xml @@ -4367,4 +4367,12 @@ Try enclosing path to the editor with double quotes. "[PREFIX]: " + + Failed to create folder [DIRNAME]: [ERROR] + Failed to remove folder [DIRNAME]: [ERROR] + Failed to open file "[FILENAME]": [ERROR] + Failed to close file: [ERROR] + Failed to remove file [FILENAME]: [ERROR] + Failed to rename file [FILE] to [NEWFILE]: [ERROR] +