* Copyright (c) 2017-2023 Google, Inc. All rights reserved.
* **********************************************************/
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * 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.
*
* * Neither the name of Google, Inc. nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 VMWARE, INC. OR CONTRIBUTORS 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 "directory_iterator.h"
#ifdef WINDOWS
# include <algorithm>
#else
# include <dirent.h>
#endif
#include <string>
#include "dr_frontend.h"
#include "utils.h"
namespace dynamorio {
namespace drmemtrace {
directory_iterator_t::directory_iterator_t(const std::string &directory)
{
#ifdef UNIX
dir_ = opendir(directory.c_str());
if (dir_ == nullptr) {
error_descr_ = "Failed to access directory.";
return;
}
++*this;
#else
find_ = INVALID_HANDLE_VALUE;
_snprintf(path_, BUFFER_SIZE_ELEMENTS(path_), "%s\\*", directory.c_str());
NULL_TERMINATE_BUFFER(path_);
if (drfront_char_to_tchar(path_, wdir_, BUFFER_SIZE_ELEMENTS(wdir_)) !=
DRFRONT_SUCCESS) {
error_descr_ = "Failed to convert from utf-8 to utf-16";
return;
}
path_[0] = '\0';
++*this;
#endif
at_eof_ = false;
}
directory_iterator_t::~directory_iterator_t()
{
#ifdef UNIX
if (dir_ != nullptr)
closedir(dir_);
#else
if (find_ != INVALID_HANDLE_VALUE)
FindClose(find_);
#endif
}
const std::string &
directory_iterator_t::operator*()
{
return cur_file_;
}
directory_iterator_t &
directory_iterator_t::operator++()
{
#ifdef UNIX
ent_ = readdir(dir_);
if (ent_ == nullptr)
at_eof_ = true;
else
cur_file_ = ent_->d_name;
#else
if (find_ == INVALID_HANDLE_VALUE) {
find_ = FindFirstFileW(wdir_, &data_);
if (find_ == INVALID_HANDLE_VALUE) {
error_descr_ = "Failed to list directory";
at_eof_ = true;
return *this;
}
} else if (!FindNextFile(find_, &data_)) {
at_eof_ = true;
return *this;
}
while (TESTANY(data_.dwFileAttributes, FILE_ATTRIBUTE_DIRECTORY)) {
if (!FindNextFile(find_, &data_)) {
at_eof_ = true;
return *this;
}
}
if (drfront_tchar_to_char(data_.cFileName, path_, BUFFER_SIZE_ELEMENTS(path_)) !=
DRFRONT_SUCCESS) {
error_descr_ = "Failed to convert from utf-16 to utf-8";
at_eof_ = true;
return *this;
}
cur_file_ = path_;
#endif
return *this;
}
bool
directory_iterator_t::is_directory(const std::string &path)
{
bool is_dir;
drfront_status_t res = drfront_dir_exists(path.c_str(), &is_dir);
return res == DRFRONT_SUCCESS && is_dir;
}
bool
directory_iterator_t::create_directory(const std::string &path_in)
{
std::string path = path_in;
#ifdef WINDOWS
std::replace(path.begin(), path.end(), ALT_DIRSEP[0], DIRSEP[0]);
#endif
drfront_status_t res;
auto pos = path.find(DIRSEP, 1);
while (pos != std::string::npos) {
std::string sub = path.substr(0, pos);
if (!is_directory(sub)) {
res = drfront_create_dir(sub.c_str());
if (res != DRFRONT_SUCCESS)
return false;
}
pos = path.find(DIRSEP, pos + 1);
}
return drfront_create_dir(path.c_str()) == DRFRONT_SUCCESS;
}
}
}