Update all the files
Some checks failed
C/C++ CI / build (push) Failing after 22s

This commit is contained in:
pavlik_dev 2024-10-17 17:47:44 +03:00
parent 283dd16393
commit 79a724e837

587
main.cpp
View File

@ -1,3 +1,12 @@
// == Config, imports are on line N
#define TABS " " // What will be used instead of tabs?
#define MAX_FILES 50 // Maximum number of files that fileinfo will process
#define FILESIZE "n" // "mib" = 1024 bytes == 1 Mbyte
// "mb" = 1000 bytes == 1 Mbyte
// "b" = Don't simplify sizes
// "n" = Use both
// Set this if you don't want MIME types // Set this if you don't want MIME types
//#define NO_MIME //#define NO_MIME
#include <iostream> #include <iostream>
@ -7,9 +16,11 @@
#include <cstring> #include <cstring>
#include <unistd.h> #include <unistd.h>
#ifndef NO_MIME #ifndef NO_MIME
#include "mime.h" #include <magic.h> // On error try running `make nomime`
#include "archives.h" // Run make nomime #else
#include "mime.cpp"
#endif #endif
#include "archives.h"
#include <string> #include <string>
#include <vector> #include <vector>
#include <array> #include <array>
@ -17,363 +28,339 @@
#include <dirent.h> #include <dirent.h>
#include <fstream> #include <fstream>
#include "devinfo.c"
void ListPartitions(const std::string& device) {
std::ifstream file("/proc/partitions");
std::string line;
while (std::getline(file, line)) {
if (line.find(device) != std::string::npos) {
std::cout << line << std::endl;
}
}
}
enum FileType { enum FileType {
Unknown, Unknown,
File, Folder, File, Folder,
BLKFile, CHRFile, BLKFile, CHRFile,
FIFO, Symlink, FIFO, Symlink,
Socket, Socket,
#ifndef NO_MIME Archive, Audio,
Archive, Audio, Application,
Application, Video, Binary,
Video, Binary, Text
Text
#endif
}; };
std::array<int, 4> get_files_in_directory(const std::string& path) std::array<int, 4> get_files_in_directory(const std::string& path)
{ {
DIR* dp = opendir(path.c_str()); DIR* dp = opendir(path.c_str());
// int normal, hidden; // int normal, hidden;
std::array<int, 2> normal = {0, 0}; std::array<int, 2> normal = {0, 0};
std::array<int, 2> hidden = {0, 0}; std::array<int, 2> hidden = {0, 0};
if (dp != nullptr) { if (dp != nullptr) {
struct dirent* ep; struct dirent* ep;
while((ep = readdir(dp))) { while((ep = readdir(dp))) {
// if (ep->d_name[0] != '.') i++; // if (ep->d_name[0] != '.') i++;
if (strcmp(ep->d_name, ".") != 0 && strcmp(ep->d_name, "..") != 0) { if (strcmp(ep->d_name, ".") != 0 && strcmp(ep->d_name, "..") != 0) {
if (ep->d_name[0] == '.') { if (ep->d_name[0] == '.') {
hidden[(ep->d_type == DT_DIR) ? 1 : 0]++; hidden[(ep->d_type == DT_DIR) ? 1 : 0]++;
}else { }else {
normal[(ep->d_type == DT_DIR) ? 1 : 0]++; normal[(ep->d_type == DT_DIR) ? 1 : 0]++;
}
}
} }
}
(void)closedir(dp);
} }
else
perror("Couldn't open the directory"); (void)closedir(dp);
std::array<int, 4> result; }
result[0] = normal[0]; else
result[1] = normal[1]; perror("Couldn't open the directory");
result[2] = hidden[0]; std::array<int, 4> result;
result[3] = hidden[1]; result[0] = normal[0];
return result; result[1] = normal[1];
result[2] = hidden[0];
result[3] = hidden[1];
return result;
} }
bool starts_with(const std::string& prefix, const std::string& string) { bool starts_with(const std::string& prefix, const std::string& string) {
return string.rfind(prefix, 0) == 0; return string.rfind(prefix, 0) == 0;
} }
#ifndef NO_MIME
bool is_archive(const std::string& mime_type) bool is_archive(const std::string& mime_type)
{ {
const std::string archives[] = ARCHIVES; const std::string archives[] = ARCHIVES;
int len = sizeof(archives)/sizeof(archives[0]); int len = sizeof(archives)/sizeof(archives[0]);
for(int i = 0; i < len; ++i) for(int i = 0; i < len; ++i)
{
if(starts_with(archives[i], mime_type))
{ {
if(starts_with(archives[i], mime_type)) return true;
{
return true;
}
} }
return false; }
return false;
} }
#endif
std::string get_name_from_filetype(const enum FileType fs) std::string get_name_from_filetype(const enum FileType fs)
{ {
switch (fs) { switch (fs) {
#ifndef NO_MIME case FileType::Application:
case FileType::Application: return "Application";
return "Application"; case FileType::Archive:
case FileType::Archive: return "Archive";
return "Archive"; case FileType::Audio:
case FileType::Audio: return "Audio";
return "Audio"; case FileType::Binary:
case FileType::Binary: return "Binary";
return "Binary"; case FileType::File:
#endif return "File";
case FileType::File: case FileType::Folder:
return "File"; return "Folder";
case FileType::Folder: case FileType::BLKFile:
return "Folder"; return "Block special file";
case FileType::BLKFile: case FileType::CHRFile:
return "Block special file"; return "Character special file";
case FileType::CHRFile: case FileType::FIFO:
return "Character special file"; return "Pipe or FIFO special file";
case FileType::FIFO: case FileType::Socket:
return "Pipe or FIFO special file"; return "UNIX socket";
case FileType::Socket: case FileType::Symlink:
return "UNIX socket"; return "Symbolic link";
case FileType::Symlink: case FileType::Text:
return "Symbolic"; return "Text";
#ifndef NO_MIME case FileType::Video:
case FileType::Text: return "Video";
return "Text"; default:
case FileType::Video: return "Unknown";
return "Video"; }
#endif
default:
return "Unknown";
}
} }
std::string get_emoji_from_filetype(const enum FileType fs) std::string get_emoji_from_filetype(const enum FileType fs)
{ {
#ifndef NO_EMOJIS #ifndef NO_EMOJIS
switch (fs) { switch (fs) {
#ifndef NO_MIME case FileType::Application:
case FileType::Application: return "⚙️";
return "⚙️"; case FileType::Archive:
case FileType::Archive: return "🗜️";
return "🗜️"; case FileType::Audio:
case FileType::Audio: return "🎵";
return "🎵"; case FileType::Binary:
case FileType::Binary: return "⚙️";
return "⚙️"; case FileType::File:
#endif return "📄";
case FileType::File: case FileType::Folder:
return "📄"; return "📁";
case FileType::Folder: case FileType::BLKFile:
return "📁"; return "🪄";
case FileType::BLKFile: case FileType::CHRFile:
return "🪄"; return "🖨️";
case FileType::CHRFile: case FileType::FIFO:
return "🖨️"; return "🤝";
case FileType::FIFO: case FileType::Socket:
return "🤝"; return "🔌";
case FileType::Socket: case FileType::Symlink:
return "🔌"; return "🔗";
case FileType::Symlink: case FileType::Text:
return "🔗"; return "📝";
#ifndef NO_MIME case FileType::Video:
case FileType::Text: return "🎥";
return "📝"; default:
case FileType::Video: return "?";
return "🎥"; }
#endif #else
default: return "";
return "?"; #endif
}
#else
return "";
#endif
} }
std::string readable_fs(const long int size /*in bytes*/, std::string readable_fs(const long int size /*in bytes*/,
const double divide_by = 1024, const double divide_by = 1024,
const std::string& suffix = "B") const std::string& suffix = "B")
{ {
if(size < 1024) { if(size < 1024) {
char buffer[128];
sprintf(buffer, "%i B", static_cast<int>(size));
std::string result(buffer);
return buffer;
}
auto result = static_cast<double>(size);
int i = 0;
const std::string units[] = {"", "K", "M", "G", "T", "P", "E", "Z", "Y"};
while (result > divide_by) {
result /= divide_by;
i++;
}
char buffer[128]; char buffer[128];
sprintf(buffer, "%.*f %s%s", i, result, units[i].c_str(), suffix.c_str()); sprintf(buffer, "%i B", static_cast<int>(size));
std::string str_result(buffer); std::string result(buffer);
return str_result; return buffer;
}
auto result = static_cast<double>(size);
int i = 0;
const std::string units[] = {"", "K", "M", "G", "T", "P", "E", "Z", "Y"};
while (result > divide_by) {
result /= divide_by;
i++;
}
char buffer[128];
sprintf(buffer, "%.*f %s%s", i, result, units[i].c_str(), suffix.c_str());
std::string str_result(buffer);
return str_result;
} }
#ifndef NO_MIME
std::string get_mime(const std::string& filename) std::string get_mime(const std::string& filename)
{ {
const char* file_path = filename.c_str(); #ifndef NO_MIME
const auto magic_cookie = static_cast<const magic_t>(magic_open(MAGIC_MIME_TYPE)); const char* file_path = filename.c_str();
if (magic_cookie == nullptr) { const auto magic_cookie = static_cast<const magic_t>(magic_open(MAGIC_MIME_TYPE));
std::cerr << "Unable to initialize libmagic\n"; if (magic_cookie == nullptr) {
return ""; std::cerr << "Unable to initialize libmagic\n";
} return "";
}
// Load definitions from the mime types database // Load definitions from the mime types database
if (magic_load(magic_cookie, nullptr) != 0) { if (magic_load(magic_cookie, nullptr) != 0) {
std::cerr << "Unable to load database definitions\n"; std::cerr << "Unable to load database definitions\n";
magic_close(magic_cookie);
return "";
}
// Determines the MIME type of the file
const char *mime_type = magic_file(magic_cookie, file_path);
if (mime_type == nullptr) {
std::cerr << "Unable to determine the MIME type of the file\n";
magic_close(magic_cookie);
return "";
}
std::string result(mime_type);
// Close libmagic
magic_close(magic_cookie); magic_close(magic_cookie);
return "";
}
return result; // Determines the MIME type of the file
const char *mime_type = magic_file(magic_cookie, file_path);
if (mime_type == nullptr) {
std::cerr << "Unable to determine the MIME type of the file\n";
magic_close(magic_cookie);
return "";
}
std::string result(mime_type);
// Close libmagic
magic_close(magic_cookie);
#else
std::string extension = filename.substr(filename.find_last_of(".")+1);
std::string result = guessMime(extension);
#endif
return result;
} }
#endif
std::string print_permissions(mode_t mode, bool is_dir) { std::string print_permissions(mode_t mode, bool is_dir) {
std::string user; std::string user;
user += (mode & S_IRUSR) ? "r" : "-"; user += (mode & S_IRUSR) ? "r" : "-";
user += (mode & S_IWUSR) ? "w" : "-", user += (mode & S_IWUSR) ? "w" : "-",
user += (mode & S_IXUSR) ? "x" : "-"; user += (mode & S_IXUSR) ? "x" : "-";
std::string group; std::string group;
group += (mode & S_IRGRP) ? "r" : "-"; group += (mode & S_IRGRP) ? "r" : "-";
group += (mode & S_IWGRP) ? "w" : "-"; group += (mode & S_IWGRP) ? "w" : "-";
group += (mode & S_IXGRP) ? "x" : "-"; group += (mode & S_IXGRP) ? "x" : "-";
std::string other; std::string other;
other += (mode & S_IROTH) ? "r" : "-"; other += (mode & S_IROTH) ? "r" : "-";
other += (mode & S_IWOTH) ? "w" : "-"; other += (mode & S_IWOTH) ? "w" : "-";
other += (mode & S_IXOTH) ? "x" : "-"; other += (mode & S_IXOTH) ? "x" : "-";
return (is_dir ? "d" : "-") + user + group + other; return (is_dir ? "d" : "-") + user + group + other;
} }
std::string basename(const std::string& filepath) { std::string basename(const std::string& filepath) {
return filepath.substr(filepath.find_last_of("/\\") + 1); return filepath.substr(filepath.find_last_of("/\\") + 1);
} }
FileType getFileType(mode_t st_mode) { FileType getFileType(mode_t st_mode) {
if(S_ISBLK(st_mode)) return FileType::BLKFile; if(S_ISBLK(st_mode)) return FileType::BLKFile;
if(S_ISCHR(st_mode)) return FileType::CHRFile; if(S_ISCHR(st_mode)) return FileType::CHRFile;
if(S_ISDIR(st_mode)) return FileType::Folder; if(S_ISDIR(st_mode)) return FileType::Folder;
if(S_ISFIFO(st_mode)) return FileType::FIFO; if(S_ISFIFO(st_mode)) return FileType::FIFO;
if(S_ISLNK(st_mode)) return FileType::Symlink; if(S_ISLNK(st_mode)) return FileType::Symlink;
if(S_ISSOCK(st_mode)) return FileType::Socket; if(S_ISSOCK(st_mode)) return FileType::Socket;
if(S_ISREG(st_mode)) return FileType::File; if(S_ISREG(st_mode)) return FileType::File;
return FileType::Unknown;
} }
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
bool absolute = false; bool absolute = false;
#ifndef NO_EMOJIS #ifndef NO_EMOJIS
bool emojis = true; bool emojis = true;
#else #else
bool emojis = false; bool emojis = false;
#endif #endif
if (argc < 2) { if (argc < 2) {
std::cerr << "Usage:\n\t" << argv[0] << " [args] filename ...\n"; std::cerr << "Usage:\n\t" << argv[0] << " [args] filename ...\n";
std::cerr << "Args:" << std::endl; std::cerr << "Args:" << std::endl;
std::cerr << "\t-A Output absolute path" << std::endl; std::cerr << "\t-A Output absolute path" << std::endl;
std::cerr << "\t-E Do not show emojis" << std::endl; std::cerr << "\t-E Do not show emojis" << std::endl;
return 255; return 255;
}
std::vector<std::string> files;
for (int i = 1; i < argc; ++i) {
if (argv[i][0] != '-') {
std::string temp(argv[i]);
files.insert(files.end(), temp);
} else {
std::string arg(argv[i]);
if(arg == "-A") {
absolute = true;
}
if (arg == "-E") {
emojis = false;
}
} }
std::vector<std::string> files; }
for (int i = 1; i < argc; ++i) {
if (argv[i][0] != '-') { size_t last = files.size();
std::string temp(argv[i]); if (last > MAX_FILES)
files.insert(files.end(), temp); printf("Too much files, showing only %i...\n", MAX_FILES);
} else { for (size_t i = 0; i < last || i < MAX_FILES; ++i) {
std::string arg(argv[i]); const std::string& filename = files[i];
if(arg == "-A") { char* c_filename = const_cast<char*>(filename.c_str());
absolute = true;
} struct stat file_stat = {};
if (arg == "-E") {
emojis = false; if (stat(filename.c_str(), &file_stat) != 0) {
} perror("stat");
} return 1;
}
// start
FileType file = getFileType(file_stat.st_mode);
bool is_file = file == FileType::File;
char temp[4097] = {'\0'};
if (realpath(c_filename, temp) == nullptr) {
perror("realpath");
return 1;
}
std::string full_name(temp); // = malloc(4097);
// delete[] temp;
std::string name = basename(full_name);
if(file == FileType::Folder) name += "/";
std::string mime_type = get_mime(full_name);
//file = (is_file) ? FileType::File : FileType::Folder;
if (file == FileType::File) {
if (is_archive(mime_type)) {
file = FileType::Archive;
} else if (starts_with("application/octet-stream", mime_type)) {
file = FileType::Binary;
} else if (starts_with("application", mime_type)) {
file = FileType::Application;
} else if (starts_with("audio", mime_type)) {
file = FileType::Audio;
} else if (starts_with("video", mime_type)) {
file = FileType::Video;
} else if (starts_with("text", mime_type)) {
file = FileType::Text;
} else {
file = FileType::Binary;
}
} }
size_t last = files.size(); std::string type = get_name_from_filetype(file);
for (size_t i = 0; i < last; ++i) { std::string emoji = get_emoji_from_filetype(file);
const std::string& filename = files[i]; if (emojis) printf("%s ", emoji.c_str());
char* c_filename = const_cast<char*>(filename.c_str()); printf("\033[1m%s\033[0m:\n", name.c_str());
printf("%sName: %s\n", TABS, name.c_str());
struct stat file_stat = {}; printf("%sType: %s\n", TABS, type.c_str());
if (absolute) printf("%sAbsolute path: %s\n", TABS, full_name.c_str());
if (stat(filename.c_str(), &file_stat) != 0) { printf("%sMIME: %s\n", TABS, mime_type.c_str());
perror("stat"); if (is_file) {
return 1; std::string _1024 = readable_fs(file_stat.st_size, 1000, "B");
} std::string _1000 = readable_fs(file_stat.st_size, 1024, "iB");
// start if (file_stat.st_size >= 1000) printf("%sFile size: %s or %s (%li bytes)\n", TABS, _1024.c_str(), _1000.c_str(), file_stat.st_size);
FileType file = getFileType(file_stat.st_mode); else printf("%sFile size: %li bytes\n", TABS, file_stat.st_size);
bool is_file = file == FileType::File; } else if (file == FileType::Folder) {
char temp[4097] = {'\0'}; auto insides = get_files_in_directory(full_name);
if (realpath(c_filename, temp) == nullptr) { printf("%sContents:\n", TABS);
perror("realpath"); printf("%s%sNormal: %i files and %i folders.\n", TABS, TABS, insides[0], insides[1]);
return 1; printf("%s%sHidden: %i files and %i folders.\n", TABS, TABS, insides[2], insides[3]);
} // Coming soon
std::string full_name(temp); // = malloc(4097); //} else if (file == FileType::CHRFile) {
// delete[] temp; // ListPartitions(full_name);
std::string name = basename(full_name);
if(file == FileType::Folder) name += "/";
#ifndef NO_MIME
std::string mime_type = get_mime(full_name);
//file = (is_file) ? FileType::File : FileType::Folder;
#else
std::string mime_type = "application/octet-stream (no mime)";
#endif
if (starts_with("inode/directory", mime_type) || !is_file) {
file = FileType::Folder;
} else if (is_archive(mime_type)) {
file = FileType::Archive;
} else if (starts_with("application/octet-stream", mime_type)) {
file = FileType::Binary;
} else if (starts_with("application", mime_type)) {
file = FileType::Application;
} else if (starts_with("audio", mime_type)) {
file = FileType::Audio;
} else if (starts_with("video", mime_type)) {
file = FileType::Video;
} else if (starts_with("text", mime_type)) {
file = FileType::Text;
} else {
file = FileType::Binary;
}
std::string type = get_name_from_filetype(file);
std::string emoji = get_emoji_from_filetype(file);
if (emojis) printf("%s ", emoji.c_str());
printf("\033[1m%s\033[0m:\n", name.c_str());
printf("\tName: %s\n", name.c_str());
printf("\tType: %s\n", type.c_str());
if (absolute) printf("\tAbsolute path: %s\n", full_name.c_str());
#ifndef NO_MIME
printf("\tMIME: %s\n", mime_type.c_str());
#endif
if (is_file) {
std::string _1024 = readable_fs(file_stat.st_size, 1000, "B");
std::string _1000 = readable_fs(file_stat.st_size, 1024, "iB");
if (file_stat.st_size >= 1000) printf("\tFile size: %s or %s (%li bytes)\n", _1024.c_str(), _1000.c_str(), file_stat.st_size);
else printf("\tFile size: %li bytes\n", file_stat.st_size);
} else if (file == FileType::Folder) {
auto insides = get_files_in_directory(full_name);
printf("\tContents:\n");
printf("\t\tNormal: %i files and %i folders.\n", insides[0], insides[1]);
printf("\t\tHidden: %i files and %i folders.\n", insides[2], insides[3]);
} else if (file == FileType::CHRFile) {
ListPartitions(full_name);
}
printf("\tPermissions: %s\n", print_permissions(file_stat.st_mode, !is_file).c_str());
if (i != last-1) {
printf("\n");
}
} }
printf("%sPermissions: %s\n", TABS, print_permissions(file_stat.st_mode, (file == FileType::Folder)).c_str());
if (i != last-1) {
printf("\n");
}
}
return 0; return 0;
} }