device_manager_4_linux/lib/libsources/fs.cpp

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());
}