blob: 5e043830073488ed495eebf2ddbede7c1c0c836d [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <log4cxx/file.h>
#include <apr_file_io.h>
#include <apr_file_info.h>
#include <log4cxx/helpers/transcoder.h>
#include <log4cxx/helpers/pool.h>
namespace LOG4CXX_NS
{
template<class S>
static LogString decodeLS(const S* src)
{
LogString dst;
if (src != 0)
{
helpers::Transcoder::decode(src, dst);
}
return dst;
}
template<class S>
static LogString decodeLS(const std::basic_string<S>& src)
{
LogString dst;
helpers::Transcoder::decode(src, dst);
return dst;
}
char* getPath(helpers::Pool& p, const File& f)
{
int style = APR_FILEPATH_ENCODING_UNKNOWN;
apr_filepath_encoding(&style, p.getAPRPool());
char* retval = NULL;
if (style == APR_FILEPATH_ENCODING_UTF8)
{
retval = helpers::Transcoder::encodeUTF8(getPath(f), p);
}
else
{
retval = helpers::Transcoder::encode(getPath(f), p);
}
return retval;
}
char* convertBackSlashes(char* src)
{
for (char* c = src; *c != 0; c++)
{
if (*c == '\\')
{
*c = '/';
}
}
return src;
}
std::vector<LogString> getFileList(helpers::Pool& p, const File& dir)
{
apr_dir_t* dir;
apr_finfo_t entry;
std::vector<LogString> filenames;
apr_status_t stat = apr_dir_open(&dir,
convertBackSlashes(getPath(p, dir)),
p.getAPRPool());
if (stat == APR_SUCCESS)
{
int style = APR_FILEPATH_ENCODING_UNKNOWN;
apr_filepath_encoding(&style, p.getAPRPool());
stat = apr_dir_read(&entry, APR_FINFO_DIRENT, dir);
while (stat == APR_SUCCESS)
{
if (entry.name != NULL)
{
LogString filename;
if (style == APR_FILEPATH_ENCODING_UTF8)
{
helpers::Transcoder::decodeUTF8(entry.name, filename);
}
else
{
helpers::Transcoder::decode(entry.name, filename);
}
filenames.push_back(filename);
}
stat = apr_dir_read(&entry, APR_FINFO_DIRENT, dir);
}
stat = apr_dir_close(dir);
}
return filenames;
}
} // namespace LOG4CXX_NS
#if LOG4CXX_FILE_IS_FILESYSTEM_PATH
namespace LOG4CXX_NS
{
bool deleteFile(helpers::Pool&, const File& f)
{
FileErrorCode ec;
return remove(f, ec);
}
LogString getPath(const File& f)
{
#if LOG4CXX_LOGCHAR_IS_UTF8
return f.string();
#elif LOG4CXX_LOGCHAR_IS_WCHAR_T
return f.wstring();
#else
return decodeLS(f.wstring());
#endif
}
LogString getParent(helpers::Pool&, const File& f)
{
LogString result;
if (f.has_parent_path())
result = getPath(f.parent_path());
return result;
}
log4cxx_time_t lastModified(helpers::Pool&, const File& f)
{
log4cxx_time_t result = 0;
FileErrorCode ec;
auto ftime = last_write_time(f, ec);
if (!ec)
{
result = std::chrono::system_clock::to_time_t(clock_cast<std::chrono::system_clock>(ftime));
}
return result;
}
size_t length(helpers::Pool&, const File& f)
{
size_t result = 0;
FileErrorCode ec;
auto fsize = file_size(f, ec);
if (!ec)
{
result = static_cast<size_t>(fsize);
}
return result;
}
bool mkdirs(helpers::Pool&, const File& f)
{
FileErrorCode ec;
return create_directories(f, ec);
}
log4cxx_status_t openFile(const File& f, apr_file_t** file, int flags, int perm, helpers::Pool& p)
{
return apr_file_open(file, getPath(p, f), flags, perm, p.getAPRPool());
}
} // namespace LOG4CXX_NS
#else // !LOG4CXX_FILE_IS_FILESYSTEM_PATH
#include <assert.h>
#include <log4cxx/helpers/exception.h>
using namespace LOG4CXX_NS;
using namespace LOG4CXX_NS::helpers;
struct File::FilePrivate{
FilePrivate() :
autoDelete(false)
{}
FilePrivate(LogString path) :
path(path),
autoDelete(false)
{}
FilePrivate(LogString path, bool autoDelete) :
path(path),
autoDelete(autoDelete)
{}
LogString path;
bool autoDelete;
};
File::File() :
m_priv(std::make_unique<FilePrivate>())
{
}
File::File(const std::string& name)
#if LOG4CXX_LOGCHAR_IS_UTF8
: m_priv(std::make_unique<FilePrivate>(name))
#else
: m_priv(std::make_unique<FilePrivate>(decodeLS(name)))
#endif
{
}
File::File(const char* name)
#if LOG4CXX_LOGCHAR_IS_UTF8
: m_priv(std::make_unique<FilePrivate>(name))
#else
: m_priv(std::make_unique<FilePrivate>(decodeLS(name)))
#endif
{
}
#if LOG4CXX_WCHAR_T_API || LOG4CXX_LOGCHAR_IS_WCHAR_T
File::File(const std::wstring& name)
#if LOG4CXX_LOGCHAR_IS_WCHAR_T
: m_priv(std::make_unique<FilePrivate>(name))
#else
: m_priv(std::make_unique<FilePrivate>(decodeLS(name)))
#endif
{
}
File::File(const wchar_t* name1)
#if LOG4CXX_LOGCHAR_IS_WCHAR_T
: m_priv(std::make_unique<FilePrivate>(name))
#else
: m_priv(std::make_unique<FilePrivate>(decodeLS(name1)))
#endif
{
}
#endif
#if LOG4CXX_UNICHAR_API || LOG4CXX_LOGCHAR_IS_UNICHAR
File::File(const std::basic_string<UniChar>& name1)
: m_priv(std::make_unique<FilePrivate>(decodeLS(name1)))
{
}
File::File(const UniChar* name1)
: m_priv(std::make_unique<FilePrivate>(decodeLS(name1)))
{
}
#endif
#if LOG4CXX_CFSTRING_API
File::File(const CFStringRef& name1)
: m_priv(std::make_unique<FilePrivate>(decodeLS(name1)))
{
}
#endif
File::File(const File& src)
: m_priv(std::make_unique<FilePrivate>(src.m_priv->path, src.m_priv->autoDelete))
{
}
File& File::operator=(const File& src)
{
if (this == &src)
{
return *this;
}
m_priv->path.assign(src.m_priv->path);
m_priv->autoDelete = src.m_priv->autoDelete;
return *this;
}
File& File::operator=(const LogString& newName)
{
m_priv->path.assign(newName);
return *this;
}
File::~File()
{
if(m_priv->autoDelete){
Pool p;
deleteFile(p);
}
}
LogString File::getPath() const
{
return m_priv->path;
}
File& File::setPath(const LogString& newName)
{
m_priv->path.assign(newName);
return *this;
}
LogString File::getName() const
{
const logchar slashes[] = { 0x2F, 0x5C, 0 };
size_t lastSlash = m_priv->path.find_last_of(slashes);
if (lastSlash != LogString::npos)
{
return m_priv->path.substr(lastSlash + 1);
}
return m_priv->path;
}
char* File::getPath(Pool& p) const
{
return ::getPath(p, *this);
}
log4cxx_status_t File::open(apr_file_t** file, int flags,
int perm, Pool& p) const
{
return apr_file_open(file, getPath(p), flags, perm, p.getAPRPool());
}
bool File::exists(Pool& p) const
{
apr_finfo_t finfo;
apr_status_t rv = apr_stat(&finfo, getPath(p),
0, p.getAPRPool());
return rv == APR_SUCCESS;
}
char* File::convertBackSlashes(char* src)
{
for (char* c = src; *c != 0; c++)
{
if (*c == '\\')
{
*c = '/';
}
}
return src;
}
bool File::deleteFile(Pool& p) const
{
apr_status_t rv = apr_file_remove(convertBackSlashes(getPath(p)),
p.getAPRPool());
return rv == APR_SUCCESS;
}
bool File::renameTo(const File& dest, Pool& p) const
{
apr_status_t rv = apr_file_rename(convertBackSlashes(getPath(p)),
convertBackSlashes(dest.getPath(p)),
p.getAPRPool());
return rv == APR_SUCCESS;
}
size_t File::length(Pool& pool) const
{
apr_finfo_t finfo;
apr_status_t rv = apr_stat(&finfo, getPath(pool),
APR_FINFO_SIZE, pool.getAPRPool());
if (rv == APR_SUCCESS)
{
return (size_t) finfo.size;
}
return 0;
}
log4cxx_time_t File::lastModified(Pool& pool) const
{
apr_finfo_t finfo;
apr_status_t rv = apr_stat(&finfo, getPath(pool),
APR_FINFO_MTIME, pool.getAPRPool());
if (rv == APR_SUCCESS)
{
return finfo.mtime;
}
return 0;
}
std::vector<LogString> File::list(Pool& p) const
{
return getFileList(p, *this);
}
LogString File::getParent(Pool&) const
{
LogString::size_type slashPos = m_priv->path.rfind(LOG4CXX_STR('/'));
LogString::size_type backPos = m_priv->path.rfind(LOG4CXX_STR('\\'));
if (slashPos == LogString::npos)
{
slashPos = backPos;
}
else
{
if (backPos != LogString::npos && backPos > slashPos)
{
slashPos = backPos;
}
}
LogString parent;
if (slashPos != LogString::npos && slashPos > 0)
{
parent.assign(m_priv->path, 0, slashPos);
}
return parent;
}
bool File::mkdirs(Pool& p) const
{
apr_status_t stat = apr_dir_make_recursive(convertBackSlashes(getPath(p)),
APR_OS_DEFAULT, p.getAPRPool());
return stat == APR_SUCCESS;
}
void File::setAutoDelete(bool autoDelete){
m_priv->autoDelete = autoDelete;
}
bool File::getAutoDelete() const{
return m_priv->autoDelete;
}
#endif // !LOG4CXX_FILE_IS_FILESYSTEM_PATH