386 lines
13 KiB
C++
Executable File
386 lines
13 KiB
C++
Executable File
//-----------------------------------------------------------------------------------------//
|
|
// Distributed under the MIT License - https://opensource.org/licenses/MIT
|
|
//-----------------------------------------------------------------------------------------//
|
|
//
|
|
// Copyright © 2019 Sasko Usinov
|
|
//
|
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
// of this software and associated documentation files (the "Software"), to deal
|
|
// in the Software without restriction, including without limitation the rights to
|
|
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
|
// the Software, and to permit persons to whom the Software is furnished to do so,
|
|
// subject to the following conditions:
|
|
//
|
|
// The above copyright notice and this permission notice shall be included in all
|
|
// copies or substantial portions of the Software.
|
|
//
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
|
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
|
// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
|
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
|
// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
|
|
// OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
//
|
|
//-----------------------------------------------------------------------------------------//
|
|
// Distributed under the MIT License - https://opensource.org/licenses/MIT
|
|
//-----------------------------------------------------------------------------------------//
|
|
|
|
|
|
#include "api.h"
|
|
#include "liblogman/log_manager.h"
|
|
|
|
#include <iostream>
|
|
#include <string>
|
|
#include <sstream>
|
|
|
|
#include <sys/klog.h>
|
|
#include <sys/stat.h>
|
|
|
|
#include <stdio.h>
|
|
#include <iostream>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <sstream>
|
|
#include <fstream>
|
|
#include <dirent.h>
|
|
|
|
#include <algorithm>
|
|
|
|
api::log_manager api::fs::g_out, api::fs::g_err(api::log_manager::level_err);
|
|
|
|
//-------------------------------------------------------------------------------//
|
|
// Type: namespace
|
|
//-------------------------------------------------------------------------------//
|
|
//
|
|
// ToDo: n/a
|
|
//
|
|
// Notes: Checks to see whether the given file_path is a directory
|
|
//
|
|
// Returns: true if so otherwise false
|
|
//
|
|
//------------------------------------------------------------------------------//
|
|
bool api::fs::is_directory(const std::string & file_path)
|
|
{
|
|
struct stat pstat;
|
|
|
|
stat(file_path.c_str(), & pstat);
|
|
|
|
return S_ISDIR(pstat.st_mode);
|
|
}
|
|
|
|
//-------------------------------------------------------------------------------//
|
|
// Type: namespace
|
|
//-------------------------------------------------------------------------------//
|
|
//
|
|
// ToDo: n/a
|
|
//
|
|
// Notes: Attempts to create a directory at the given dir_path
|
|
//
|
|
// Returns: true if so otherwise false
|
|
//
|
|
//------------------------------------------------------------------------------//
|
|
bool api::fs::create_directory(const std::string & dir_path)
|
|
{
|
|
if (mkdir(dir_path.c_str(), 0700) == 0)
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
//-------------------------------------------------------------------------------//
|
|
// Type: namespace
|
|
//-------------------------------------------------------------------------------//
|
|
//
|
|
// ToDo: n/a
|
|
//
|
|
// Notes: Checks to see whether the given file_path exists
|
|
//
|
|
// Returns: true if pathe exists otherwise false
|
|
//
|
|
//------------------------------------------------------------------------------//
|
|
bool api::fs::path_exists(const std::string & file_path)
|
|
{
|
|
struct stat buffer;
|
|
return (stat(file_path.c_str(), &buffer) == 0);
|
|
}
|
|
|
|
//-------------------------------------------------------------------------------//
|
|
// Type: namespace
|
|
//-------------------------------------------------------------------------------//
|
|
//
|
|
// ToDo: n/a
|
|
//
|
|
// Notes: Saves the contents of content to file_path
|
|
//
|
|
// Returns: true on success otherwise false
|
|
//
|
|
//------------------------------------------------------------------------------//
|
|
bool api::fs::save_to_file(const std::string & file_path, const std::string & content, bool append)
|
|
{
|
|
try
|
|
{
|
|
std::ofstream file_stream (file_path.c_str(), append ? std::ofstream::out | std::ofstream::app : std::ofstream::out);
|
|
|
|
if (!file_stream.is_open())
|
|
return false;
|
|
|
|
file_stream << content.c_str();
|
|
|
|
file_stream.close();
|
|
}
|
|
catch (std::exception & e)
|
|
{
|
|
glogger << NAME_TO_STRING(API_ERROR_FILE_WRITE) << " when opening " << file_path << ". Error is: " << e.what();
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
//-------------------------------------------------------------------------------//
|
|
// Type: namespace
|
|
//-------------------------------------------------------------------------------//
|
|
//
|
|
// ToDo: n/a
|
|
//
|
|
// Notes: Returns the contents of local file
|
|
//
|
|
// Returns: A string containing the contents of the loaded file
|
|
//
|
|
//------------------------------------------------------------------------------//
|
|
std::string api::fs::load_from_file(const std::string & local_file)
|
|
{
|
|
try
|
|
{
|
|
std::ifstream ifs(local_file.c_str());
|
|
|
|
if (!ifs.is_open()) return std::string();
|
|
|
|
std::string str((std::istreambuf_iterator<char>(ifs)), std::istreambuf_iterator<char>());
|
|
ifs.close();
|
|
|
|
return str;
|
|
}
|
|
catch (std::exception & e)
|
|
{
|
|
glogger << NAME_TO_STRING(API_ERROR_FILE_OPEN) << " when opening " << local_file << " for reading. Error is: " << e.what();
|
|
return std::string();
|
|
}
|
|
}
|
|
|
|
//-------------------------------------------------------------------------------//
|
|
// Type: namespace
|
|
//-------------------------------------------------------------------------------//
|
|
//
|
|
// ToDo: n/a
|
|
//
|
|
// Notes: Creates a unique file name in path - one that does not exist yet
|
|
// at the time this function runs.
|
|
//
|
|
// Note, it does *not* create the file. It simply generates a file name
|
|
// that is available at the time this function runs.
|
|
//
|
|
// It's possible for another process to generate the same file name at random
|
|
// between the time this function returns and the next executing statement
|
|
// in main line and then you end up in a situation where two processes work
|
|
// with the same file while you are completely oblivious to it.
|
|
//
|
|
// (What are the odds of that?)
|
|
//
|
|
// Returns: The path to the available file name at the time this function ran
|
|
//
|
|
// Remarks: Consider using mkstemp()
|
|
//
|
|
//------------------------------------------------------------------------------//
|
|
std::string api::fs::generate_unique_filename(const std::string & path, const std::string & prefix, int start_idx, const char & sep)
|
|
{
|
|
if (!api::fs::path_exists(path))
|
|
return std::string();
|
|
|
|
std::string base_path {path};
|
|
std::string path_del {'/'};
|
|
int idx {start_idx};
|
|
std::string logfile {prefix};
|
|
|
|
(base_path[base_path.length() - 1] != path_del[0]) ? base_path += path_del : base_path;
|
|
|
|
while (api::fs::path_exists(base_path + (idx < 10 ? "0" + std::to_string(idx) : std::to_string(idx)) + std::string(1, sep) + logfile))
|
|
idx++;
|
|
|
|
return base_path + (idx < 10 ? "0" + std::to_string(idx) : std::to_string(idx)) + std::string(1, sep) + logfile;
|
|
}
|
|
|
|
|
|
//-------------------------------------------------------------------------------//
|
|
// Type: namespace
|
|
//-------------------------------------------------------------------------------//
|
|
//
|
|
// ToDo: n/a
|
|
//
|
|
// Notes: Obtains a file listing in dir_path
|
|
//
|
|
// Returns: A vector listing of strings containing the path to the files
|
|
//
|
|
//
|
|
//
|
|
//------------------------------------------------------------------------------//
|
|
std::vector<std::string> api::fs::get_file_list(const std::string & dir_path)
|
|
{
|
|
std::vector<std::string> lst;
|
|
DIR * dir;
|
|
struct dirent * drn;
|
|
|
|
dir = opendir (dir_path.c_str());
|
|
|
|
if (!dir) return std::vector<std::string>();
|
|
|
|
while ((drn = readdir (dir)) != nullptr)
|
|
{
|
|
if (std::string(drn->d_name) == ".") continue;
|
|
if (std::string(drn->d_name) == "..") continue;
|
|
|
|
lst.push_back((dir_path[dir_path.length() - 1] == '/') ? dir_path + drn->d_name : dir_path + "/" + drn->d_name);
|
|
}
|
|
|
|
closedir (dir);
|
|
|
|
std::sort(lst.begin(), lst.end()); // C++11 ...
|
|
|
|
return lst;
|
|
}
|
|
|
|
//-------------------------------------------------------------------------------//
|
|
// Type: namespace
|
|
//-------------------------------------------------------------------------------//
|
|
//
|
|
// ToDo: n/a
|
|
//
|
|
// Notes: Obtains a file listing in dir_path
|
|
//
|
|
// Returns: A vector listing of strings containing the path to the files
|
|
//
|
|
//------------------------------------------------------------------------------//
|
|
std::vector<std::string> api::fs::get_file_list_via_shell(const std::string & dir_path)
|
|
{
|
|
std::vector<std::string> lst {(dir_path[0] != '"' && dir_path[dir_path.size() - 1] != '"') ?
|
|
(api::vct::to_vector_string_list(api::cns::run("ls -d \"" + dir_path + "\"/* 2> /dev/null"), std::vector<char>() = {10,13}, WITH_NO_TERM_CHARS)) :
|
|
(api::vct::to_vector_string_list(api::cns::run("ls -d " + dir_path + "/* 2> /dev/null"), std::vector<char>() = {10,13}, WITH_NO_TERM_CHARS))};
|
|
|
|
if (!lst.size()) return lst;
|
|
|
|
lst.erase(lst.begin() + static_cast<int>(lst.size() - 1));
|
|
|
|
for (size_t i = 0; i < lst.size(); i++)
|
|
lst[i] = api::str::trim(lst[i]);
|
|
|
|
return lst;
|
|
}
|
|
|
|
//-------------------------------------------------------------------------------//
|
|
// Type: namespace
|
|
//-------------------------------------------------------------------------------//
|
|
//
|
|
// ToDo: n/a
|
|
//
|
|
// Notes: Removes non-dirs in the speciefied dir_path
|
|
//
|
|
// Returns:
|
|
//
|
|
//------------------------------------------------------------------------------//
|
|
void api::fs::remove_non_dirs(const std::string & dir_path)
|
|
{
|
|
std::vector<std::string> file_list = api::fs::get_file_list(dir_path);
|
|
|
|
for (size_t i = 0; i < file_list.size(); i++)
|
|
{
|
|
if (!api::fs::is_directory(file_list[i]))
|
|
system(std::string("rm \"" + file_list[i] + "\"").c_str());
|
|
}
|
|
}
|
|
|
|
//-------------------------------------------------------------------------------//
|
|
// Type: namespace
|
|
//-------------------------------------------------------------------------------//
|
|
//
|
|
// ToDo: n/a
|
|
//
|
|
// Notes: Removes all files in dir_path except the ones listed in lst
|
|
//
|
|
// Returns:
|
|
//
|
|
//------------------------------------------------------------------------------//
|
|
void api::fs::remove_all_except(const std::string & dir_path, const std::vector<std::string> & lst)
|
|
{
|
|
std::vector<std::string> file_list = api::fs::get_file_list(dir_path);
|
|
|
|
for (size_t i = 0; i < file_list.size(); i++)
|
|
{
|
|
for (size_t x = 0; x < lst.size(); x++)
|
|
{
|
|
if (file_list[i] == lst[x])
|
|
continue;
|
|
|
|
if (path_exists(file_list[i]))
|
|
system(std::string("rm \"" + file_list[i] + "\"").c_str());
|
|
}
|
|
}
|
|
}
|
|
|
|
//-------------------------------------------------------------------------------//
|
|
// Type: namespace
|
|
//-------------------------------------------------------------------------------//
|
|
//
|
|
// ToDo: n/a
|
|
//
|
|
// Notes: Renames a file
|
|
//
|
|
// Returns: True on success
|
|
//
|
|
//------------------------------------------------------------------------------//
|
|
int api::fs::rename_file(const std::string & full_file_path, const std::string & new_name_no_path)
|
|
{
|
|
std::string file_path {api::str::range_copy(0,
|
|
api::str::get_char_index('/', api::str::char_count('/', full_file_path), full_file_path),
|
|
full_file_path)};
|
|
|
|
std::string cmd {std::string("mv \"" + full_file_path + "\" \"" + file_path + new_name_no_path + "\"")};
|
|
|
|
if (full_file_path == (file_path + new_name_no_path))
|
|
return true;
|
|
|
|
return !system(cmd.c_str());
|
|
}
|
|
|
|
//-------------------------------------------------------------------------------//
|
|
// Type: namespace
|
|
//-------------------------------------------------------------------------------//
|
|
//
|
|
// ToDo: n/a
|
|
//
|
|
// Notes: Delets a file (including a directory)
|
|
//
|
|
// Returns: True on success
|
|
//
|
|
//------------------------------------------------------------------------------//
|
|
int api::fs::remove_file(const std::string & file_path)
|
|
{
|
|
return !system(std::string("rm -rf \"" + file_path + "\"").c_str());
|
|
}
|
|
|
|
//-------------------------------------------------------------------------------//
|
|
// Type: namespace
|
|
//-------------------------------------------------------------------------------//
|
|
//
|
|
// ToDo: n/a
|
|
//
|
|
// Notes: Creates a symbolic link
|
|
//
|
|
// Returns: True on success
|
|
//
|
|
//------------------------------------------------------------------------------//
|
|
int api::fs::symbolic_link(const std::string & source, const std::string & target)
|
|
{
|
|
return !system(std::string("ln -s \"" + source + "\" \"" + target + "\"").c_str());
|
|
}
|