Compare commits
6 Commits
45919eabab
...
2025-08-10
| Author | SHA1 | Date | |
|---|---|---|---|
| 2bc28d47cd | |||
| 214a4045f0 | |||
| 3df13fdfa6 | |||
| 6011365330 | |||
| 03db5b4b0a | |||
| b1d4c8af07 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -16,3 +16,4 @@ coffee_crisis*
|
|||||||
debug.txt
|
debug.txt
|
||||||
cppcheck-result*
|
cppcheck-result*
|
||||||
desktop.ini
|
desktop.ini
|
||||||
|
ccae_release/
|
||||||
@@ -81,7 +81,9 @@ set(APP_SOURCES
|
|||||||
source/input_types.cpp
|
source/input_types.cpp
|
||||||
source/mouse.cpp
|
source/mouse.cpp
|
||||||
source/options.cpp
|
source/options.cpp
|
||||||
|
source/shutdown.cpp
|
||||||
source/stage.cpp
|
source/stage.cpp
|
||||||
|
source/system_utils.cpp
|
||||||
source/utils.cpp
|
source/utils.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
72
Makefile
72
Makefile
@@ -22,37 +22,42 @@ RASPI_RELEASE := $(TARGET_FILE)-$(VERSION)-raspberry.tar.gz
|
|||||||
|
|
||||||
# Lista completa de archivos fuente (basada en CMakeLists.txt)
|
# Lista completa de archivos fuente (basada en CMakeLists.txt)
|
||||||
APP_SOURCES := \
|
APP_SOURCES := \
|
||||||
|
source/animated_sprite.cpp \
|
||||||
source/asset.cpp \
|
source/asset.cpp \
|
||||||
source/audio.cpp \
|
source/audio.cpp \
|
||||||
source/director.cpp \
|
source/background.cpp \
|
||||||
source/global_events.cpp \
|
|
||||||
source/global_inputs.cpp \
|
|
||||||
source/input.cpp \
|
|
||||||
source/lang.cpp \
|
|
||||||
source/main.cpp \
|
|
||||||
source/param.cpp \
|
|
||||||
source/resource.cpp \
|
|
||||||
source/screen.cpp \
|
|
||||||
source/text.cpp \
|
|
||||||
source/writer.cpp \
|
|
||||||
source/ui/menu_option.cpp \
|
|
||||||
source/ui/menu_renderer.cpp \
|
|
||||||
source/ui/notifier.cpp \
|
|
||||||
source/ui/service_menu.cpp \
|
|
||||||
source/ui/ui_message.cpp \
|
|
||||||
source/ui/window_message.cpp \
|
|
||||||
source/balloon_formations.cpp \
|
source/balloon_formations.cpp \
|
||||||
source/balloon_manager.cpp \
|
source/balloon_manager.cpp \
|
||||||
source/balloon.cpp \
|
source/balloon.cpp \
|
||||||
source/bullet.cpp \
|
source/bullet.cpp \
|
||||||
|
source/color.cpp \
|
||||||
|
source/define_buttons.cpp \
|
||||||
|
source/difficulty.cpp \
|
||||||
|
source/director.cpp \
|
||||||
source/enter_name.cpp \
|
source/enter_name.cpp \
|
||||||
source/explosions.cpp \
|
source/explosions.cpp \
|
||||||
|
source/external/gif.cpp \
|
||||||
|
source/external/jail_audio.cpp \
|
||||||
|
source/external/jail_shader.cpp \
|
||||||
|
source/fade.cpp \
|
||||||
source/game_logo.cpp \
|
source/game_logo.cpp \
|
||||||
|
source/global_events.cpp \
|
||||||
|
source/global_inputs.cpp \
|
||||||
|
source/input_types.cpp \
|
||||||
|
source/input.cpp \
|
||||||
source/item.cpp \
|
source/item.cpp \
|
||||||
|
source/lang.cpp \
|
||||||
|
source/main.cpp \
|
||||||
source/manage_hiscore_table.cpp \
|
source/manage_hiscore_table.cpp \
|
||||||
|
source/mouse.cpp \
|
||||||
|
source/moving_sprite.cpp \
|
||||||
|
source/options.cpp \
|
||||||
|
source/param.cpp \
|
||||||
|
source/path_sprite.cpp \
|
||||||
source/player.cpp \
|
source/player.cpp \
|
||||||
|
source/resource.cpp \
|
||||||
source/scoreboard.cpp \
|
source/scoreboard.cpp \
|
||||||
source/tabe.cpp \
|
source/screen.cpp \
|
||||||
source/sections/credits.cpp \
|
source/sections/credits.cpp \
|
||||||
source/sections/game.cpp \
|
source/sections/game.cpp \
|
||||||
source/sections/hiscore_table.cpp \
|
source/sections/hiscore_table.cpp \
|
||||||
@@ -60,26 +65,23 @@ APP_SOURCES := \
|
|||||||
source/sections/intro.cpp \
|
source/sections/intro.cpp \
|
||||||
source/sections/logo.cpp \
|
source/sections/logo.cpp \
|
||||||
source/sections/title.cpp \
|
source/sections/title.cpp \
|
||||||
source/animated_sprite.cpp \
|
source/shutdown.cpp \
|
||||||
source/background.cpp \
|
|
||||||
source/fade.cpp \
|
|
||||||
source/moving_sprite.cpp \
|
|
||||||
source/path_sprite.cpp \
|
|
||||||
source/smart_sprite.cpp \
|
source/smart_sprite.cpp \
|
||||||
source/sprite.cpp \
|
source/sprite.cpp \
|
||||||
|
source/stage.cpp \
|
||||||
|
source/system_utils.cpp \
|
||||||
|
source/tabe.cpp \
|
||||||
|
source/text.cpp \
|
||||||
source/texture.cpp \
|
source/texture.cpp \
|
||||||
source/tiled_bg.cpp \
|
source/tiled_bg.cpp \
|
||||||
source/color.cpp \
|
source/ui/menu_option.cpp \
|
||||||
source/define_buttons.cpp \
|
source/ui/menu_renderer.cpp \
|
||||||
source/difficulty.cpp \
|
source/ui/notifier.cpp \
|
||||||
source/input_types.cpp \
|
source/ui/service_menu.cpp \
|
||||||
source/mouse.cpp \
|
source/ui/ui_message.cpp \
|
||||||
source/options.cpp \
|
source/ui/window_message.cpp \
|
||||||
source/stage.cpp \
|
|
||||||
source/utils.cpp \
|
source/utils.cpp \
|
||||||
source/external/jail_shader.cpp \
|
source/writer.cpp
|
||||||
source/external/jail_audio.cpp \
|
|
||||||
source/external/gif.cpp
|
|
||||||
|
|
||||||
# Includes
|
# Includes
|
||||||
INCLUDES := -Isource -Isource/external
|
INCLUDES := -Isource -Isource/external
|
||||||
@@ -242,7 +244,7 @@ linux_release:
|
|||||||
|
|
||||||
# Empaqueta ficheros
|
# Empaqueta ficheros
|
||||||
$(RMFILE) "$(LINUX_RELEASE)"
|
$(RMFILE) "$(LINUX_RELEASE)"
|
||||||
cd "$(RELEASE_FOLDER)" && tar -czvf "../$(LINUX_RELEASE)" *
|
tar -czvf "$(LINUX_RELEASE)" -C "$(RELEASE_FOLDER)" .
|
||||||
|
|
||||||
# Elimina la carpeta temporal
|
# Elimina la carpeta temporal
|
||||||
$(RMDIR) "$(RELEASE_FOLDER)"
|
$(RMDIR) "$(RELEASE_FOLDER)"
|
||||||
@@ -272,7 +274,7 @@ raspi_release:
|
|||||||
|
|
||||||
# Empaqueta ficheros
|
# Empaqueta ficheros
|
||||||
$(RMFILE) "$(RASPI_RELEASE)"
|
$(RMFILE) "$(RASPI_RELEASE)"
|
||||||
cd "$(RELEASE_FOLDER)" && tar -czvf "../$(RASPI_RELEASE)" *
|
tar -czvf "$(RASPI_RELEASE)" -C "$(RELEASE_FOLDER)" .
|
||||||
|
|
||||||
# Elimina la carpeta temporal
|
# Elimina la carpeta temporal
|
||||||
$(RMDIR) "$(RELEASE_FOLDER)"
|
$(RMDIR) "$(RELEASE_FOLDER)"
|
||||||
|
|||||||
@@ -8,9 +8,8 @@ fi
|
|||||||
|
|
||||||
FILE="$1"
|
FILE="$1"
|
||||||
|
|
||||||
include-what-you-use -D DEBUG -D VERBOSE -std=c++20 -Wall "$FILE" \
|
include-what-you-use -D _DEBUG -std=c++20 -Wall "$FILE" \
|
||||||
|
-I../source \
|
||||||
-Xiwyu --mapping_file=sdl3_mapping.imp \
|
-Xiwyu --mapping_file=sdl3_mapping.imp \
|
||||||
-Xiwyu --update_comments \
|
-Xiwyu --update_comments \
|
||||||
-Xiwyu --verbose=3 \
|
-Xiwyu --verbose=3
|
||||||
| \
|
|
||||||
python3 /usr/bin/fix_includes.py --update_comments
|
|
||||||
@@ -1,20 +1,17 @@
|
|||||||
// IWYU pragma: no_include <bits/chrono.h>
|
// IWYU pragma: no_include <bits/chrono.h>
|
||||||
#include "director.h"
|
#include "director.h"
|
||||||
|
|
||||||
#include <SDL3/SDL.h> // Para SDL_LogCategory, SDL_LogInfo, SDL_SetLogPriority, SDL_LogPriority, SDL_Quit
|
#include <SDL3/SDL.h> // Para SDL_LogInfo, SDL_LogCategory, SDL_SetLogPriority, SDL_LogPriority, SDL_Quit
|
||||||
#include <sys/stat.h> // Para mkdir, stat, S_IRWXU
|
|
||||||
#include <unistd.h> // Para getuid
|
|
||||||
|
|
||||||
#include <cerrno> // Para errno, EEXIST, EACCES, ENAMETOOLONG
|
#include <cstdlib> // Para srand, exit, rand, EXIT_FAILURE
|
||||||
#include <cstdio> // Para printf, perror
|
|
||||||
#include <cstdlib> // Para exit, EXIT_FAILURE, srand, rand, system
|
|
||||||
#include <ctime> // Para time
|
#include <ctime> // Para time
|
||||||
|
#include <iostream> // Para basic_ostream, operator<<, cerr, endl
|
||||||
#include <memory> // Para make_unique, unique_ptr
|
#include <memory> // Para make_unique, unique_ptr
|
||||||
#include <span> // Para span
|
#include <span> // Para span
|
||||||
#include <stdexcept> // Para runtime_error
|
#include <stdexcept> // Para runtime_error
|
||||||
#include <string> // Para operator+, allocator, char_traits, operator==, string, basic_string
|
#include <string> // Para allocator, char_traits, operator==, string, basic_string, operator+
|
||||||
|
|
||||||
#include "asset.h" // Para Asset, AssetType
|
#include "asset.h" // Para Asset
|
||||||
#include "audio.h" // Para Audio
|
#include "audio.h" // Para Audio
|
||||||
#include "input.h" // Para Input
|
#include "input.h" // Para Input
|
||||||
#include "lang.h" // Para setLanguage
|
#include "lang.h" // Para setLanguage
|
||||||
@@ -32,14 +29,12 @@
|
|||||||
#include "sections/intro.h" // Para Intro
|
#include "sections/intro.h" // Para Intro
|
||||||
#include "sections/logo.h" // Para Logo
|
#include "sections/logo.h" // Para Logo
|
||||||
#include "sections/title.h" // Para Title
|
#include "sections/title.h" // Para Title
|
||||||
|
#include "shutdown.h" // Para resultToString, shutdownSystem, ShutdownResult
|
||||||
|
#include "system_utils.h" // Para createApplicationFolder, resultToString, Result
|
||||||
#include "ui/notifier.h" // Para Notifier
|
#include "ui/notifier.h" // Para Notifier
|
||||||
#include "ui/service_menu.h" // Para ServiceMenu
|
#include "ui/service_menu.h" // Para ServiceMenu
|
||||||
#include "utils.h" // Para Overrides, overrides, getPath
|
#include "utils.h" // Para Overrides, overrides, getPath
|
||||||
|
|
||||||
#ifndef _WIN32
|
|
||||||
#include <pwd.h> // Para getpwuid, passwd
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
Director::Director(int argc, std::span<char *> argv) {
|
Director::Director(int argc, std::span<char *> argv) {
|
||||||
#ifdef RECORDING
|
#ifdef RECORDING
|
||||||
@@ -83,11 +78,7 @@ void Director::init() {
|
|||||||
// Configuración inicial de parametros
|
// Configuración inicial de parametros
|
||||||
Asset::init(executable_path_); // Inicializa el sistema de gestión de archivos
|
Asset::init(executable_path_); // Inicializa el sistema de gestión de archivos
|
||||||
loadAssets(); // Crea el índice de archivos
|
loadAssets(); // Crea el índice de archivos
|
||||||
|
Input::init(Asset::get()->get("gamecontrollerdb.txt"), Asset::get()->get("controllers.json")); // Carga configuración de controles
|
||||||
Input::init(
|
|
||||||
Asset::get()->get("gamecontrollerdb.txt"),
|
|
||||||
Asset::get()->get("controllers.json")); // Carga configuración de controles
|
|
||||||
|
|
||||||
Options::setConfigFile(Asset::get()->get("config.txt")); // Establece el fichero de configuración
|
Options::setConfigFile(Asset::get()->get("config.txt")); // Establece el fichero de configuración
|
||||||
Options::setControllersFile(Asset::get()->get("controllers.json")); // Establece el fichero de configuración de mandos
|
Options::setControllersFile(Asset::get()->get("controllers.json")); // Establece el fichero de configuración de mandos
|
||||||
Options::loadFromFile(); // Carga el archivo de configuración
|
Options::loadFromFile(); // Carga el archivo de configuración
|
||||||
@@ -193,57 +184,13 @@ void Director::checkProgramArguments(int argc, std::span<char *> argv) {
|
|||||||
|
|
||||||
// Crea la carpeta del sistema donde guardar datos
|
// Crea la carpeta del sistema donde guardar datos
|
||||||
void Director::createSystemFolder(const std::string &folder) {
|
void Director::createSystemFolder(const std::string &folder) {
|
||||||
#ifdef _WIN32
|
auto result = SystemUtils::createApplicationFolder(folder, system_folder_);
|
||||||
system_folder_ = std::string(getenv("APPDATA")) + "/" + folder;
|
|
||||||
#elif __APPLE__
|
|
||||||
struct passwd *pw = getpwuid(getuid());
|
|
||||||
const char *homedir = pw->pw_dir;
|
|
||||||
system_folder_ = std::string(homedir) + "/Library/Application Support" + "/" + folder;
|
|
||||||
#elif __linux__
|
|
||||||
struct passwd *pw = getpwuid(getuid());
|
|
||||||
const char *homedir = pw->pw_dir;
|
|
||||||
system_folder_ = std::string(homedir) + "/.config/" + folder;
|
|
||||||
|
|
||||||
{
|
if (result != SystemUtils::Result::SUCCESS) {
|
||||||
// Intenta crear ".config", per si no existeix
|
std::cerr << "Error creando carpeta del sistema: "
|
||||||
std::string config_base_folder = std::string(homedir) + "/.config";
|
<< SystemUtils::resultToString(result) << std::endl;
|
||||||
int ret = mkdir(config_base_folder.c_str(), S_IRWXU);
|
|
||||||
if (ret == -1 && errno != EEXIST) {
|
|
||||||
printf("ERROR CREATING CONFIG BASE FOLDER.");
|
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct stat st = {0};
|
|
||||||
if (stat(system_folder_.c_str(), &st) == -1) {
|
|
||||||
errno = 0;
|
|
||||||
#ifdef _WIN32
|
|
||||||
int ret = mkdir(system_folder_.c_str());
|
|
||||||
#else
|
|
||||||
int ret = mkdir(system_folder_.c_str(), S_IRWXU);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (ret == -1) {
|
|
||||||
switch (errno) {
|
|
||||||
case EACCES:
|
|
||||||
printf("the parent directory does not allow write");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
|
|
||||||
case EEXIST:
|
|
||||||
printf("pathname already exists");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
|
|
||||||
case ENAMETOOLONG:
|
|
||||||
printf("pathname is too long");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
|
|
||||||
default:
|
|
||||||
perror("mkdir");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ejecuta la sección con el logo
|
// Ejecuta la sección con el logo
|
||||||
@@ -368,21 +315,13 @@ auto Director::run() -> int {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apaga el sistema
|
// Apaga el sistema de forma segura
|
||||||
void Director::shutdownSystem(bool should_shutdown) {
|
void Director::shutdownSystem(bool should_shutdown) {
|
||||||
if (should_shutdown) {
|
if (should_shutdown) {
|
||||||
#ifdef _WIN32
|
auto result = SystemShutdown::shutdownSystem(5, true); // 5 segundos, forzar apps
|
||||||
// Apaga el sistema en Windows
|
|
||||||
system("shutdown /s /t 5");
|
if (result != SystemShutdown::ShutdownResult::SUCCESS) {
|
||||||
#elif __APPLE__
|
std::cerr << SystemShutdown::resultToString(result) << std::endl;
|
||||||
// Apaga el sistema en macOS
|
}
|
||||||
system("sudo shutdown -h +0.1");
|
|
||||||
#elif __linux__
|
|
||||||
// Apaga el sistema en Linux
|
|
||||||
system("sleep 5; shutdown -h now");
|
|
||||||
#else
|
|
||||||
// Sistema operativo no compatible
|
|
||||||
#error "Sistema operativo no soportado"
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <span>
|
#include <span> // Para Span
|
||||||
#include <string> // Para manejar cadenas de texto
|
#include <string> // Para string
|
||||||
|
|
||||||
namespace Lang {
|
namespace Lang {
|
||||||
enum class Code : int;
|
enum class Code : int;
|
||||||
|
|||||||
155
source/shutdown.cpp
Normal file
155
source/shutdown.cpp
Normal file
@@ -0,0 +1,155 @@
|
|||||||
|
#include "shutdown.h"
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <windows.h>
|
||||||
|
#else
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#include <string>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace SystemShutdown {
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
|
// Función auxiliar para sistemas Unix-like
|
||||||
|
ShutdownResult executeUnixShutdown(const char* command, char* const args[]) {
|
||||||
|
pid_t pid = fork();
|
||||||
|
|
||||||
|
if (pid == 0) {
|
||||||
|
// Proceso hijo
|
||||||
|
execvp(command, args);
|
||||||
|
// Si llegamos aquí, execvp falló
|
||||||
|
std::cerr << "Error: No se pudo ejecutar " << command << std::endl;
|
||||||
|
_exit(1);
|
||||||
|
} else if (pid > 0) {
|
||||||
|
// Proceso padre
|
||||||
|
int status;
|
||||||
|
waitpid(pid, &status, 0);
|
||||||
|
return (WEXITSTATUS(status) == 0) ? ShutdownResult::SUCCESS : ShutdownResult::ERROR_SYSTEM_CALL;
|
||||||
|
} else {
|
||||||
|
return ShutdownResult::ERROR_FORK_FAILED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Implementación de las funciones públicas
|
||||||
|
ShutdownResult shutdownSystem() {
|
||||||
|
ShutdownConfig config;
|
||||||
|
return shutdownSystem(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
ShutdownResult shutdownSystem(int delay_seconds, bool force_apps) {
|
||||||
|
ShutdownConfig config;
|
||||||
|
config.delay_seconds = delay_seconds;
|
||||||
|
config.force_close_apps = force_apps;
|
||||||
|
return shutdownSystem(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
ShutdownResult shutdownSystem(const ShutdownConfig& config) {
|
||||||
|
#ifdef _WIN32
|
||||||
|
// Windows: Usar CreateProcess
|
||||||
|
STARTUPINFOA si = {0};
|
||||||
|
PROCESS_INFORMATION pi = {0};
|
||||||
|
si.cb = sizeof(si);
|
||||||
|
|
||||||
|
// Crear comando con el delay especificado
|
||||||
|
std::string command = "shutdown.exe /s /t " + std::to_string(config.delay_seconds);
|
||||||
|
if (config.force_close_apps) {
|
||||||
|
command += " /f";
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateProcess necesita un array de char modificable
|
||||||
|
char* cmd_buffer = new char[command.length() + 1];
|
||||||
|
strcpy(cmd_buffer, command.c_str());
|
||||||
|
|
||||||
|
bool success = CreateProcessA(
|
||||||
|
NULL, // lpApplicationName
|
||||||
|
cmd_buffer, // lpCommandLine
|
||||||
|
NULL, // lpProcessAttributes
|
||||||
|
NULL, // lpThreadAttributes
|
||||||
|
FALSE, // bInheritHandles
|
||||||
|
0, // dwCreationFlags
|
||||||
|
NULL, // lpEnvironment
|
||||||
|
NULL, // lpCurrentDirectory
|
||||||
|
&si, // lpStartupInfo
|
||||||
|
&pi // lpProcessInformation
|
||||||
|
);
|
||||||
|
|
||||||
|
delete[] cmd_buffer;
|
||||||
|
|
||||||
|
if (success) {
|
||||||
|
CloseHandle(pi.hProcess);
|
||||||
|
CloseHandle(pi.hThread);
|
||||||
|
return ShutdownResult::SUCCESS;
|
||||||
|
} else {
|
||||||
|
DWORD error = GetLastError();
|
||||||
|
if (error == ERROR_ACCESS_DENIED) {
|
||||||
|
return ShutdownResult::ERROR_PERMISSION;
|
||||||
|
}
|
||||||
|
return ShutdownResult::ERROR_SYSTEM_CALL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif __APPLE__
|
||||||
|
// macOS - apagado inmediato
|
||||||
|
char* args[] = {
|
||||||
|
const_cast<char*>("shutdown"),
|
||||||
|
const_cast<char*>("-h"),
|
||||||
|
const_cast<char*>("now"),
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
return executeUnixShutdown("shutdown", args);
|
||||||
|
|
||||||
|
#elif __linux__
|
||||||
|
// Linux - apagado inmediato
|
||||||
|
char* args[] = {
|
||||||
|
const_cast<char*>("shutdown"),
|
||||||
|
const_cast<char*>("-h"),
|
||||||
|
const_cast<char*>("now"),
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
return executeUnixShutdown("shutdown", args);
|
||||||
|
|
||||||
|
#else
|
||||||
|
return ShutdownResult::ERROR_UNSUPPORTED;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* resultToString(ShutdownResult result) {
|
||||||
|
switch (result) {
|
||||||
|
case ShutdownResult::SUCCESS:
|
||||||
|
return "Apagado iniciado exitosamente";
|
||||||
|
case ShutdownResult::ERROR_PERMISSION:
|
||||||
|
return "Error: Permisos insuficientes";
|
||||||
|
case ShutdownResult::ERROR_SYSTEM_CALL:
|
||||||
|
return "Error: Fallo en la llamada al sistema";
|
||||||
|
case ShutdownResult::ERROR_FORK_FAILED:
|
||||||
|
return "Error: No se pudo crear proceso hijo";
|
||||||
|
case ShutdownResult::ERROR_UNSUPPORTED:
|
||||||
|
return "Error: Sistema operativo no soportado";
|
||||||
|
default:
|
||||||
|
return "Error desconocido";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isShutdownSupported() {
|
||||||
|
#if defined(_WIN32) || defined(__APPLE__) || defined(__linux__)
|
||||||
|
return true;
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* getRequiredPermissions() {
|
||||||
|
#ifdef _WIN32
|
||||||
|
return "Requiere permisos de Administrador en Windows";
|
||||||
|
#elif defined(__APPLE__) || defined(__linux__)
|
||||||
|
return "Requiere permisos de root/sudo en Unix";
|
||||||
|
#else
|
||||||
|
return "Sistema no soportado";
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace SystemShutdown
|
||||||
47
source/shutdown.h
Normal file
47
source/shutdown.h
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
// Utilidad multiplataforma para apagar el sistema de forma segura
|
||||||
|
namespace SystemShutdown {
|
||||||
|
|
||||||
|
// Códigos de resultado para las operaciones de apagado
|
||||||
|
enum class ShutdownResult {
|
||||||
|
SUCCESS = 0,
|
||||||
|
ERROR_PERMISSION, // Error de permisos insuficientes
|
||||||
|
ERROR_SYSTEM_CALL, // Error en la llamada al sistema
|
||||||
|
ERROR_FORK_FAILED, // Error al crear proceso hijo (Unix)
|
||||||
|
ERROR_UNSUPPORTED // Sistema operativo no soportado
|
||||||
|
};
|
||||||
|
|
||||||
|
// Configuración para el apagado del sistema
|
||||||
|
struct ShutdownConfig {
|
||||||
|
int delay_seconds;
|
||||||
|
bool force_close_apps;
|
||||||
|
const char* shutdown_message;
|
||||||
|
|
||||||
|
// Constructor con valores por defecto
|
||||||
|
ShutdownConfig()
|
||||||
|
: delay_seconds(5)
|
||||||
|
, force_close_apps(true)
|
||||||
|
, shutdown_message("El sistema se apagará...")
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Apaga el sistema con configuración por defecto
|
||||||
|
ShutdownResult shutdownSystem();
|
||||||
|
|
||||||
|
// Apaga el sistema con configuración personalizada
|
||||||
|
ShutdownResult shutdownSystem(const ShutdownConfig& config);
|
||||||
|
|
||||||
|
// Apaga el sistema con parámetros simples
|
||||||
|
ShutdownResult shutdownSystem(int delay_seconds, bool force_apps = true);
|
||||||
|
|
||||||
|
// Convierte un código de resultado a string descriptivo
|
||||||
|
const char* resultToString(ShutdownResult result);
|
||||||
|
|
||||||
|
// Verifica si el sistema actual soporta apagado programático
|
||||||
|
bool isShutdownSupported();
|
||||||
|
|
||||||
|
// Obtiene información sobre los permisos necesarios en la plataforma actual
|
||||||
|
const char* getRequiredPermissions();
|
||||||
|
|
||||||
|
} // namespace SystemShutdown
|
||||||
190
source/system_utils.cpp
Normal file
190
source/system_utils.cpp
Normal file
@@ -0,0 +1,190 @@
|
|||||||
|
#include "system_utils.h"
|
||||||
|
#include <iostream>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <cerrno>
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <windows.h>
|
||||||
|
#include <shlobj.h>
|
||||||
|
#include <direct.h>
|
||||||
|
// Evitar conflictos con macros de Windows
|
||||||
|
#ifdef ERROR_ALREADY_EXISTS
|
||||||
|
#undef ERROR_ALREADY_EXISTS
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#include <pwd.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace SystemUtils {
|
||||||
|
|
||||||
|
// Función auxiliar para crear una carpeta individual
|
||||||
|
Result createSingleFolder(const std::string& path, int permissions) {
|
||||||
|
struct stat st = {0};
|
||||||
|
|
||||||
|
// Verificar si ya existe
|
||||||
|
if (stat(path.c_str(), &st) == 0) {
|
||||||
|
return Result::SUCCESS; // Ya existe, no es error por defecto
|
||||||
|
}
|
||||||
|
|
||||||
|
// Intentar crear la carpeta
|
||||||
|
int result;
|
||||||
|
#ifdef _WIN32
|
||||||
|
result = _mkdir(path.c_str());
|
||||||
|
#else
|
||||||
|
result = mkdir(path.c_str(), permissions);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (result == -1) {
|
||||||
|
switch (errno) {
|
||||||
|
case EACCES:
|
||||||
|
return Result::PERMISSION_DENIED;
|
||||||
|
case EEXIST:
|
||||||
|
return Result::ALREADY_EXISTS;
|
||||||
|
case ENAMETOOLONG:
|
||||||
|
return Result::PATH_TOO_LONG;
|
||||||
|
default:
|
||||||
|
return Result::UNKNOWN_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Result::SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Función auxiliar para crear carpetas padre recursivamente
|
||||||
|
Result createParentFolders(const std::string& path, int permissions) {
|
||||||
|
size_t pos = 0;
|
||||||
|
|
||||||
|
while ((pos = path.find('/', pos + 1)) != std::string::npos) {
|
||||||
|
std::string parent = path.substr(0, pos);
|
||||||
|
if (!parent.empty() && !folderExists(parent)) {
|
||||||
|
Result result = createSingleFolder(parent, permissions);
|
||||||
|
if (result != Result::SUCCESS && result != Result::ALREADY_EXISTS) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Result::SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result createApplicationFolder(const std::string& app_name, std::string& out_path) {
|
||||||
|
FolderConfig config;
|
||||||
|
return createApplicationFolder(app_name, out_path, config);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result createApplicationFolder(const std::string& app_name, std::string& out_path, const FolderConfig& config) {
|
||||||
|
out_path = getApplicationDataPath(app_name);
|
||||||
|
return createFolder(out_path, config);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result createFolder(const std::string& path) {
|
||||||
|
FolderConfig config;
|
||||||
|
return createFolder(path, config);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result createFolder(const std::string& path, const FolderConfig& config) {
|
||||||
|
if (path.empty()) {
|
||||||
|
return Result::INVALID_PATH;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verificar si ya existe y si eso es un error
|
||||||
|
if (folderExists(path) && config.fail_if_exists) {
|
||||||
|
return Result::ALREADY_EXISTS;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Crear carpetas padre si es necesario
|
||||||
|
if (config.create_parents) {
|
||||||
|
Result parent_result = createParentFolders(path, config.permissions);
|
||||||
|
if (parent_result != Result::SUCCESS) {
|
||||||
|
return parent_result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Crear la carpeta final
|
||||||
|
return createSingleFolder(path, config.permissions);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string getApplicationDataPath(const std::string& app_name) {
|
||||||
|
#ifdef _WIN32
|
||||||
|
char* appdata = getenv("APPDATA");
|
||||||
|
if (appdata) {
|
||||||
|
return std::string(appdata) + "/" + app_name;
|
||||||
|
}
|
||||||
|
return "C:/Users/Default/AppData/Roaming/" + app_name;
|
||||||
|
|
||||||
|
#elif __APPLE__
|
||||||
|
std::string home = getHomeDirectory();
|
||||||
|
return home + "/Library/Application Support/" + app_name;
|
||||||
|
|
||||||
|
#elif __linux__
|
||||||
|
std::string home = getHomeDirectory();
|
||||||
|
return home + "/.config/" + app_name;
|
||||||
|
|
||||||
|
#else
|
||||||
|
// Fallback genérico
|
||||||
|
std::string home = getHomeDirectory();
|
||||||
|
return home + "/." + app_name;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool folderExists(const std::string& path) {
|
||||||
|
struct stat st = {0};
|
||||||
|
return (stat(path.c_str(), &st) == 0 && S_ISDIR(st.st_mode));
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* resultToString(Result result) {
|
||||||
|
switch (result) {
|
||||||
|
case Result::SUCCESS:
|
||||||
|
return "Operación exitosa";
|
||||||
|
case Result::PERMISSION_DENIED:
|
||||||
|
return "Error: Permisos insuficientes";
|
||||||
|
case Result::PATH_TOO_LONG:
|
||||||
|
return "Error: Ruta demasiado larga";
|
||||||
|
case Result::ALREADY_EXISTS:
|
||||||
|
return "Error: La carpeta ya existe";
|
||||||
|
case Result::INVALID_PATH:
|
||||||
|
return "Error: Ruta inválida";
|
||||||
|
case Result::UNKNOWN_ERROR:
|
||||||
|
return "Error desconocido";
|
||||||
|
default:
|
||||||
|
return "Error no identificado";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string getHomeDirectory() {
|
||||||
|
#ifdef _WIN32
|
||||||
|
char* userprofile = getenv("USERPROFILE");
|
||||||
|
if (userprofile) {
|
||||||
|
return std::string(userprofile);
|
||||||
|
}
|
||||||
|
return "C:/Users/Default";
|
||||||
|
#else
|
||||||
|
struct passwd *pw = getpwuid(getuid());
|
||||||
|
if (pw && pw->pw_dir) {
|
||||||
|
return std::string(pw->pw_dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fallback
|
||||||
|
char* home = getenv("HOME");
|
||||||
|
if (home) {
|
||||||
|
return std::string(home);
|
||||||
|
}
|
||||||
|
return "/tmp";
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string getTempDirectory() {
|
||||||
|
#ifdef _WIN32
|
||||||
|
char* temp = getenv("TEMP");
|
||||||
|
if (temp) {
|
||||||
|
return std::string(temp);
|
||||||
|
}
|
||||||
|
return "C:/Windows/Temp";
|
||||||
|
#else
|
||||||
|
return "/tmp";
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace SystemUtils
|
||||||
59
source/system_utils.h
Normal file
59
source/system_utils.h
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
// Utilidades multiplataforma para operaciones del sistema
|
||||||
|
namespace SystemUtils {
|
||||||
|
|
||||||
|
// Códigos de resultado para operaciones del sistema
|
||||||
|
enum class Result {
|
||||||
|
SUCCESS = 0,
|
||||||
|
PERMISSION_DENIED, // Sin permisos para crear la carpeta
|
||||||
|
PATH_TOO_LONG, // Ruta demasiado larga
|
||||||
|
ALREADY_EXISTS, // Ya existe (solo si se considera error)
|
||||||
|
INVALID_PATH, // Ruta inválida
|
||||||
|
UNKNOWN_ERROR // Error desconocido
|
||||||
|
};
|
||||||
|
|
||||||
|
// Configuración para creación de carpetas
|
||||||
|
struct FolderConfig {
|
||||||
|
bool create_parents; // Crear carpetas padre si no existen
|
||||||
|
bool fail_if_exists; // Fallar si la carpeta ya existe
|
||||||
|
int permissions; // Permisos Unix (ignorado en Windows)
|
||||||
|
|
||||||
|
// Constructor con valores por defecto
|
||||||
|
FolderConfig()
|
||||||
|
: create_parents(true)
|
||||||
|
, fail_if_exists(false)
|
||||||
|
, permissions(0755) // rwxr-xr-x
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Crea la carpeta del sistema donde guardar datos de la aplicación
|
||||||
|
Result createApplicationFolder(const std::string& app_name, std::string& out_path);
|
||||||
|
|
||||||
|
// Crea la carpeta del sistema con configuración personalizada
|
||||||
|
Result createApplicationFolder(const std::string& app_name, std::string& out_path, const FolderConfig& config);
|
||||||
|
|
||||||
|
// Crea una carpeta en la ruta especificada
|
||||||
|
Result createFolder(const std::string& path);
|
||||||
|
|
||||||
|
// Crea una carpeta con configuración personalizada
|
||||||
|
Result createFolder(const std::string& path, const FolderConfig& config);
|
||||||
|
|
||||||
|
// Obtiene la ruta de datos de la aplicación (sin crearla)
|
||||||
|
std::string getApplicationDataPath(const std::string& app_name);
|
||||||
|
|
||||||
|
// Verifica si una carpeta existe
|
||||||
|
bool folderExists(const std::string& path);
|
||||||
|
|
||||||
|
// Convierte un código de resultado a string descriptivo
|
||||||
|
const char* resultToString(Result result);
|
||||||
|
|
||||||
|
// Obtiene el directorio home del usuario
|
||||||
|
std::string getHomeDirectory();
|
||||||
|
|
||||||
|
// Obtiene el directorio temporal del sistema
|
||||||
|
std::string getTempDirectory();
|
||||||
|
|
||||||
|
} // namespace SystemUtils
|
||||||
Reference in New Issue
Block a user