device_manager_4_linux/lib/libsources/sys.cpp

318 lines
12 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
//-----------------------------------------------------------------------------------------//
#define QT_NO_KEYWORDS
#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 <algorithm>
#include <limits.h>
#include <gio/gio.h>
api::log_manager api::sys::g_out, api::sys::g_err(api::log_manager::level_err);
//-------------------------------------------------------------------------------//
// namespace
//-------------------------------------------------------------------------------//
//
// ToDo: n/a
//
// Notes: Obtains the canonical absolute name of path
//
// Returns: The absolute path to the file or blank if it fails to resolve it
//
//------------------------------------------------------------------------------//
std::string api::sys::read_link(const std::string & path)
{
char buff[PATH_MAX];
char * res = realpath(path.c_str(), buff);
return (res) ? std::string(res) : std::string();
}
//-------------------------------------------------------------------------------//
// Type: method
//-------------------------------------------------------------------------------//
//
// ToDo: n/a
//
// Notes: Requires:
// #include <gio/gio.h>
//
// Compile with:
// -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -fpermissive -lgio-2.0
//
// If using with Qt, put #define QT_NO_KEYWORDS at the top of the file
//
// Returns: n/a
//
//-------------------------------------------------------------------------------//
std::string api::sys::get_file_icon_name(const std::string & file_path)
{
// typedef std::vector<std::string> string_list;
if (!api::fs::path_exists(file_path))
return std::string();
std::string home_dir {get_env("HOME")};
GError * error;
GFile * file = g_file_new_for_path (file_path.c_str());
GFileInfo * file_info = g_file_query_info (file, "standard::*", GFileQueryInfoFlags::G_FILE_QUERY_INFO_NONE, nullptr, &error);
// const char * content_type = g_file_info_get_content_type (file_info);
// char * desc = g_content_type_get_description (content_type);
// GAppInfo * app_info = g_app_info_get_default_for_type (content_type, FALSE);
GIcon * icon = g_file_info_get_icon (file_info);
const char * file_icon = g_icon_to_string (icon);
// log "g_icon_to_string returned: \"" << file_icon << "\"";
// log "Content Type is: \"" << content_type << "\"";
// log "Description is: \"" << desc << "\"";
return file_icon;
}
//-------------------------------------------------------------------------------//
// Type: method
//-------------------------------------------------------------------------------//
//
// ToDo: n/a
//
// Notes: Requires:
// #include <gio/gio.h>
//
// Compile with:
// -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -fpermissive -lgio-2.0
//
// If using with Qt, put #define QT_NO_KEYWORDS at the top of the file
//
// Returns: n/a
//
//
// SPECIAL NOTE: This function is extremely, extremely slow and unefficient.
// Use it for single files only, not multiple files (it's slow)
//
//-------------------------------------------------------------------------------//
std::string api::sys::get_file_icon_path(const std::string & file_path, const std::vector<std::string> & icon_theme_paths, const std::string & icon_theme_name, const std::string & icon_label)
{
if (!api::fs::path_exists(file_path))
return std::string();
GError * error;
GFile * file = g_file_new_for_path (file_path.c_str());
GFileInfo * file_info = g_file_query_info (file, "standard::*", GFileQueryInfoFlags::G_FILE_QUERY_INFO_NONE, nullptr, &error);
// const char * content_type = g_file_info_get_content_type (file_info);
// char * desc = g_content_type_get_description (content_type);
// GAppInfo * app_info = g_app_info_get_default_for_type (content_type, FALSE);
GIcon * icon = g_file_info_get_icon (file_info);
const char * file_icon_name = g_icon_to_string (icon);
std::string icon_path {};
std::vector<std::string> icon_names_list {icon_label.empty() ? api::vct::to_vector_string_list(file_icon_name, 32) : std::vector<std::string> () = {icon_label}};
std::string trimmed_name {};
// log "(): g_icon_to_string returned: \"" << file_icon_name << "\"";
// log "(): Content Type is: \"" << content_type << "\"";
// log "(): Description is: \"" << desc << "\"";
for (size_t i = 0; i < icon_theme_paths.size(); i++)
{
if (icon_theme_paths[i][0] == ':') continue;
if (api::fs::path_exists(icon_theme_paths[i] + "/" + icon_theme_name))
{
for (size_t x = 0; x < icon_names_list.size(); x++)
{
trimmed_name = api::str::trim(icon_names_list[x]);
if (trimmed_name == ".") continue;
std::string icon_locate_command {"find " + icon_theme_paths[i] + "/" + icon_theme_name + " -name " + "\"" + trimmed_name + "*\""};
std::vector<std::string> paths {api::vct::to_vector_string_list(api::cns::run(icon_locate_command), std::vector<char> () = {10, 13})};
if (paths.size() > 1)
{
icon_path = api::str::trim(paths[paths.size() - 2]);
goto exit_op;
}
}
}
}
//-------------------------------------------------------------------------------//
// We failed to find the icon in the specified theme name
//-------------------------------------------------------------------------------//
if (!icon_path.size())
{
// log "DID NOT find icon in " + icon_theme_name + ". Searching other themes..." << icon_path;
for (size_t i = 0; i < icon_theme_paths.size(); i++)
{
if (icon_theme_paths[i][0] == ':') continue;
for (size_t x = 0; x < icon_names_list.size(); x++)
{
trimmed_name = api::str::trim(icon_names_list[x]);
if (trimmed_name == ".") continue;
std::string icon_locate_command {"find " + icon_theme_paths[i] + " -name " + "\"" + api::str::trim(icon_names_list[x]) + "*\""};
std::vector<std::string> paths {api::vct::to_vector_string_list(api::cns::run(icon_locate_command), std::vector<char> () = {10, 13})};
if (paths.size() > 1)
{
icon_path = api::str::trim(paths[paths.size() - 2]);
goto exit_op;
}
}
}
}
exit_op:
{
// log "Exiting, calculated icon path is: " << icon_path;
return icon_path;
}
}
//-------------------------------------------------------------------------------//
// namespace
//-------------------------------------------------------------------------------//
//
// ToDo: n/a
//
// Notes: Tries to return the library loaded search paths
//
// $ ldconfig -v 2> /dev/null | grep -v ^$'\t'
//
// /usr/lib/x86_64-linux-gnu/libfakeroot:
// /lib/i386-linux-gnu:
// /usr/local/lib:
// /lib/x86_64-linux-gnu:
// /lib32:
// /libx32:
// /lib:
// /lib/i386-linux-gnu/i686: (hwcap: 0x0002000000000000)
// /lib/i386-linux-gnu/sse2: (hwcap: 0x0000000000000001)
// /lib/i386-linux-gnu/i686/sse2: (hwcap: 0x0002000000000001)
//
// Returns: A vector of strings where each item is a separate path
//
//------------------------------------------------------------------------------//
std::vector<std::string> api::sys::get_library_loader_search_paths()
{
std::vector<std::string> tmp_list = api::vct::to_vector_string_list(api::cns::exec("ldconfig -v 2> /dev/null | grep -v ^$'\t'", "/tmp").std_out, 10, 13);
std::vector<std::string> out;
for (size_t i = 0; i < tmp_list.size(); i++)
{
if (!api::str::trim(tmp_list[i]).size())
continue;
size_t path_end = api::str::get_char_index(':', 1, tmp_list[i]);
if (path_end == API_ERROR_IDX_NOT_FOUND)
path_end = tmp_list[i].size();
out.push_back(api::str::trim(api::str::range_copy(0, path_end - 1, tmp_list[i])));
}
return out;
}
//-------------------------------------------------------------------------------//
// namespace
//-------------------------------------------------------------------------------//
//
// ToDo: n/a
//
// Notes: Runs a command in the background
//
// I am almost certain someone will hate what this code is doing
// but the reason I am doing it is because I am having issues
// launching Qt applications from my own Qt program because the runtime loads
// the wrong Qt shared libs. A perfect example of this is vlc
//
// If you do system("vlc -v &") from within my Qt applicarion or even if you
// use QProcess(), vlc won't start because ld.so loads incorrect Qt libs
// and the runtime complains about incorrect Qt versions
//
// So this is my workaround, love it, hate it, it does seem to work (around)...
//
//
// Returns: n/a
//
//------------------------------------------------------------------------------//
void api::sys::exec_background_cmd(const std::string & cmd, bool run_as_root)
{
std::string script_path {api::fs::generate_unique_filename("/tmp", "tmp-cmd")};
std::vector<std::string> script;
run_as_root ? script.push_back("#!/usr/bin/pkexec /bin/bash") : script.push_back("#!/bin/bash");
script.push_back("unset LD_LIBRARY_PATH");
script.push_back("unset QT_PLUGIN_PATH");
script.push_back("unset QT_QPA_PLATFORM_PLUGIN_PATH");
script.push_back(cmd);
if (!api::fs::save_to_file(script_path, api::vct::to_string(script, '\n')))
{
std::cerr << ": Failed at saving file: " + script_path;
return;
}
if (system(("chmod u+x " + script_path).c_str()))
{
std::cerr << ": Failed at chmoding file: " + script_path;
return;
}
std::cout << "Runnng: " << script_path;
std::system((script_path + " &" ).c_str());
}