From f5cc3a0aba4a5048812b2491155f09f0827090cc Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Mon, 14 Jan 2019 12:19:47 +0100 Subject: [PATCH] Remove some static length strings There are too many MAX_PATH_CHARACTERS length string. make Initial_directory, Data_directory, Config_directory dynamically allocated. --- src/global.h | 6 +- src/io.c | 32 +++++++++- src/io.h | 2 + src/main.c | 24 +++++--- src/setup.c | 165 ++++++++++++++++++++++++++++++--------------------- src/setup.h | 21 ++++--- 6 files changed, 157 insertions(+), 93 deletions(-) diff --git a/src/global.h b/src/global.h index ab340428..9d0052d9 100644 --- a/src/global.h +++ b/src/global.h @@ -612,11 +612,11 @@ GFX2_GLOBAL byte Airbrush_multi_flow[256]; /// Boolean, set to true to exit the program. GFX2_GLOBAL byte Quitting; /// Name of the directory that was current when the program was run. -GFX2_GLOBAL char Initial_directory[MAX_PATH_CHARACTERS]; +GFX2_GLOBAL char * Initial_directory; /// Name of the directory that holds the program's (read-only) data: skins, icon, etc. -GFX2_GLOBAL char Data_directory[MAX_PATH_CHARACTERS]; +GFX2_GLOBAL char * Data_directory; /// Name of the directory where grafx2 reads and writes configuration (gfx2.ini, gfx2.cfg) -GFX2_GLOBAL char Config_directory[MAX_PATH_CHARACTERS]; +GFX2_GLOBAL char * Config_directory; /// Current foreground color for drawing. GFX2_GLOBAL byte Fore_color; /// Current background color for drawing. diff --git a/src/io.c b/src/io.c index 83e2cf41..8eb7d0b5 100644 --- a/src/io.c +++ b/src/io.c @@ -33,7 +33,6 @@ #ifndef _MSC_VER #include #else -#include #if _MSC_VER < 1900 #define snprintf _snprintf #endif @@ -67,6 +66,7 @@ #include "realpath.h" #include "unicode.h" #include "global.h" +#include "gfx2log.h" // Lit un octet // Renvoie -1 si OK, 0 en cas d'erreur @@ -288,6 +288,36 @@ word * Find_last_separator_unicode(const word * str) return (word *)position; } +char * Filepath_append_to_dir(const char * dir, const char * filename) +{ + char * path; + size_t len = strlen(dir); + if (dir[len-1] == PATH_SEPARATOR[0] +#if defined(__WIN32__) || defined(WIN32) + || dir[len-1] == '/' +#elif __AROS__ + || dir[len-1] == ':' +#endif + ) + { + len += strlen(filename) + 1; + path = malloc(len); + if (path == NULL) + return NULL; + snprintf(path, len, "%s%s", dir, filename); + } + else + { + // need to add a path separator + len += strlen(PATH_SEPARATOR) + strlen(filename) + 1; + path = malloc(len); + if (path == NULL) + return NULL; + snprintf(path, len, "%s%s%s", dir, PATH_SEPARATOR, filename); + } + return path; +} + // Récupère la partie "nom de file seul" d'un chemin void Extract_filename(char *dest, const char *source) { diff --git a/src/io.h b/src/io.h index a960ef7a..65adffe8 100644 --- a/src/io.h +++ b/src/io.h @@ -90,6 +90,8 @@ unsigned long File_length_file(FILE * file); * Functions used to manipulate files path and names * @{ */ +/// Construct full file path +char * Filepath_append_to_dir(const char * dir, const char * filename); /// Extracts the filename part from a full file name. void Extract_filename(char *dest, const char *source); /// Extracts the directory from a full file name. diff --git a/src/main.c b/src/main.c index d45773b6..bef16b80 100644 --- a/src/main.c +++ b/src/main.c @@ -613,7 +613,7 @@ int Init_program(int argc,char * argv[]) int temp; int starting_videomode; enum IMAGE_MODES starting_image_mode; - static char program_directory[MAX_PATH_CHARACTERS]; + char * program_directory; T_Gui_skin *gfx; int file_in_command_line; T_Gradient_array initial_gradients; @@ -654,16 +654,18 @@ int Init_program(int argc,char * argv[]) Init_list_of_pages(Spare.backups); // Determine the executable directory - Set_program_directory(argv[0],program_directory); + program_directory = Get_program_directory(argv[0]); // Choose directory for data (read only) - Set_data_directory(program_directory,Data_directory); + Data_directory = Get_data_directory(program_directory); // Choose directory for settings (read/write) - Set_config_directory(program_directory,Config_directory); -// On détermine le répertoire courant: + Config_directory = Get_config_directory(program_directory); + // Get current directory Get_current_directory(Main.selector.Directory,Main.selector.Directory_unicode,MAX_PATH_CHARACTERS); + free(program_directory); + // On en profite pour le mémoriser dans le répertoire principal: - strcpy(Initial_directory,Main.selector.Directory); + Initial_directory = strdup(Main.selector.Directory); // On initialise les données sur le nom de fichier de l'image de brouillon: strcpy(Spare.selector.Directory,Main.selector.Directory); @@ -1187,7 +1189,8 @@ int Init_program(int argc,char * argv[]) return(1); } -#define FREE_POINTER(p) free(p); p = NULL //!< Make free the memory and make sure the pointer is set to NULL +/// Free the memory and make sure the pointer is set to NULL +#define FREE_POINTER(p) free(p); p = NULL /** * Program Shutdown. @@ -1226,8 +1229,7 @@ void Program_shutdown(void) Horizontal_line_buffer = NULL; // On libère le pinceau spécial - free(Paintbrush_sprite); - Paintbrush_sprite = NULL; + FREE_POINTER(Paintbrush_sprite); // Free Brushes FREE_POINTER(Brush); @@ -1276,6 +1278,10 @@ void Program_shutdown(void) else Error(ERROR_MISSING_DIRECTORY); + FREE_POINTER(Initial_directory); + FREE_POINTER(Config_directory); + FREE_POINTER(Data_directory); + // Free Config FREE_POINTER(Config.Skin_file); FREE_POINTER(Config.Font_file); diff --git a/src/setup.c b/src/setup.c index 961f5d0f..6baa7237 100644 --- a/src/setup.c +++ b/src/setup.c @@ -33,6 +33,10 @@ #include #ifdef _MSC_VER #include + #define strdup _strdup + #if _MSC_VER < 1900 + #define snprintf _snprintf + #endif #endif #elif defined(__macosx__) #import @@ -53,6 +57,7 @@ #include "io.h" #include "setup.h" #include "global.h" +#include "gfx2log.h" #ifndef PATH_MAX // This is a random default value ... @@ -70,13 +75,15 @@ int Create_ConfigDirectory(const char * config_dir) // Determine which directory contains the executable. // IN: Main's argv[0], some platforms need it, some don't. -// OUT: Write into program_dir. Trailing / or \ is kept. +// OUT: program_dir. Trailing / or \ is kept. // Note : in fact this is only used to check for the datafiles and fonts in // this same directory. -void Set_program_directory(const char * argv0, char * program_dir) +char * Get_program_directory(const char * argv0) { + char * program_dir; // MacOSX #if defined(__macosx__) + program_dir = malloc(MAXPATHLEN); CFURLRef url = CFBundleCopyBundleURL(CFBundleGetMainBundle()); (void)argv0; // unused CFURLGetFileSystemRepresentation(url,true,(UInt8*)program_dir,MAXPATHLEN); @@ -87,19 +94,19 @@ void Set_program_directory(const char * argv0, char * program_dir) // AmigaOS and alike: hard-coded volume name. #elif defined(__amigaos4__) || defined(__AROS__) || defined(__MORPHOS__) || defined(__amigaos__) (void)argv0; // unused - strcpy(program_dir,"PROGDIR:"); + program_dir = strdup("PROGDIR:"); #elif defined(__MINT__) static char path[1024]={0}; - char currentDrive='A'; + char currentDrive; + (void)argv0; // unused - currentDrive=currentDrive+Dgetdrv(); - - Dgetpath(path,0); - sprintf(program_dir,"%c:\%s",currentDrive,path); - // Append trailing slash - strcat(program_dir,PATH_SEPARATOR); + currentDrive = 'A' + Dgetdrv(); + Dgetpath(path, 0); + program_dir = malloc(4 + strlen(path) + 1); + sprintf(program_dir,"%c:\\%s%s", currentDrive, path, PATH_SEPARATOR); #elif defined(__ANDROID__) (void)argv0; // unused + progam_dir = malloc(MAX_PATH_CHARACTERS); getcwd(program_dir, MAX_PATH_CHARACTERS); strcat(program_dir, "/"); // Linux: argv[0] unreliable @@ -109,54 +116,65 @@ void Set_program_directory(const char * argv0, char * program_dir) char path[PATH_MAX]; if (readlink("/proc/self/exe", path, sizeof(path)) >= 0) { + program_dir = malloc(strlen(path) + 1); Extract_path(program_dir, path); - return; + return program_dir; } - } + } + program_dir = malloc(strlen(argv0) + 1); Extract_path(program_dir, argv0); // Others: The part of argv[0] before the executable name. // Keep the last \ or /. // On Windows, Mingw32 already provides the full path in all cases. #else + program_dir = malloc(strlen(argv0) + 1); Extract_path(program_dir, argv0); #endif + return program_dir; } -// Determine which directory contains the read-only data. -// IN: The directory containing the executable -// OUT: Write into data_dir. Trailing / or \ is kept. -void Set_data_directory(const char * program_dir, char * data_dir) +/// Determine which directory contains the read-only data. +/// @param program_dir The directory containing the executable +/// @return the path. Trailing / or \ is kept. +char * Get_data_directory(const char * program_dir) { + const char * to_append; // On all platforms, data is relative to the executable's directory - strcpy(data_dir,program_dir); - // On MacOSX, it is stored in a special folder: #if defined(__macosx__) - strcat(data_dir,"Contents/Resources/"); - // On GP2X, AROS and Android, executable is not in bin/ + // On MacOSX, it is stored in a special folder: + to_append = "Contents/Resources/"; #elif defined (__GP2X__) || defined (__gp2x__) || defined (__WIZ__) || defined (__CAANOO__) || defined(GCWZERO) || defined(__AROS__) || defined(__ANDROID__) - //strcat(data_dir,"share/grafx2/"); - strcat(data_dir, "data/"); - //on tos, the same directory is used for everything + // On GP2X, AROS and Android, executable is not in bin/ + to_append = "data/"; #elif defined (__MINT__) - strcpy(data_dir, program_dir); - //on switch, we store everything in the SD card in /switch/grafx2 + //on tos, the same directory is used for everything + return strdup(program_dir); #elif defined(__SWITCH__) - strcpy(data_dir,"/switch/grafx2/"); - // Haiku provides us with an API to find it. + //on switch, we store everything in the SD card in /switch/grafx2 + return strdup("/switch/grafx2/"); #elif defined(__HAIKU__) - if (find_path(Set_data_directory, B_FIND_PATH_DATA_DIRECTORY, "grafx2/", data_dir, PATH_MAX) != B_OK) + // Haiku provides us with an API to find it. + char * data_dir = malloc(PATH_MAX); + if (find_path(Get_data_directory, B_FIND_PATH_DATA_DIRECTORY, "grafx2/", data_dir, PATH_MAX) == B_OK) + { + return data_dir; + } + else { // If the program is not installed, find_path will fail. Try from local dir then. - strcat(data_dir,"../share/grafx2/"); + free(data_dir); + to_append = "../share/grafx2/"; } #elif defined(WIN32) - strcat(data_dir,"..\\share\\grafx2\\"); - // All other targets, program is in a "bin" subdirectory + to_append = "..\\share\\grafx2\\"; #else - strcat(data_dir,"../share/grafx2/"); + // All other targets, program is in a "bin" subdirectory + to_append = "../share/grafx2/"; #endif + + return Filepath_append_to_dir(program_dir, to_append); } // Determine which directory should store the user's configuration. @@ -170,37 +188,39 @@ void Set_data_directory(const char * program_dir, char * data_dir) // own directory. // IN: The directory containing the executable // OUT: Write into config_dir. Trailing / or \ is kept. -void Set_config_directory(const char * program_dir, char * config_dir) +char * Get_config_directory(const char * program_dir) { - // AmigaOS4 provides the PROGIR: alias to the directory where the executable is. + // AmigaOS4 provides the PROGDIR: alias to the directory where the executable is. #if defined(__amigaos4__) || defined(__AROS__) - strcpy(config_dir,"PROGDIR:"); + return strdup("PROGDIR:"); // GP2X #elif defined(__GP2X__) || defined(__WIZ__) || defined(__CAANOO__) // On the GP2X, the program is installed to the sdcard, and we don't want to mess with the system tree which is // on an internal flash chip. So, keep these settings locals. - strcpy(config_dir,program_dir); + return strdup(program_dir); // For TOS we store everything in the program dir #elif defined(__MINT__) - strcpy(config_dir,program_dir); + return strdup(program_dir); //on switch, we store everything in the SD card in /switch/grafx2 #elif defined(__SWITCH__) - strcpy(config_dir,"/switch/grafx2/"); - // For all other platforms, there is some kind of settigns dir to store this. + return strdup("/switch/grafx2/"); + // For all other platforms, there is some kind of settings dir to store this. #else - char filename[MAX_PATH_CHARACTERS]; + char * config_dir; + size_t len; + char * filename; #ifdef GCWZERO - strcpy(config_dir, "/media/home/.grafx2/"); + config_dir = strdup("/media/home/.grafx2/"); + #elif defined(__macosx__) + // On all the remaining targets except OSX, the executable is in ./bin + config_dir = strdup(program_dir); #else - // In priority: check root directory - strcpy(config_dir, program_dir); + len = strlen(program_dir) + 4; + config_dir = malloc(len); + snprintf(config_dir, len, "%s%s", program_dir, "../"); #endif - // On all the remaining targets except OSX, the executable is in ./bin - #if !defined(__macosx__) - strcat(config_dir, "../"); - #endif - strcpy(filename, config_dir); - strcat(filename, CONFIG_FILENAME); + + filename = Filepath_append_to_dir(config_dir, CONFIG_FILENAME); if (File_exists(filename)) { @@ -230,7 +250,7 @@ void Set_config_directory(const char * program_dir, char * config_dir) #elif defined(__MINT__) const char* Config_SubDir = ""; printf("GFX2.CFG not found in %s\n",filename); - strcpy(config_parent_dir, config_dir); + config_parent_dir = strdup(config_dir); #else // ~/.config/grafx2 const char* Config_SubDir; @@ -238,45 +258,52 @@ void Set_config_directory(const char * program_dir, char * config_dir) if (config_parent_dir) Config_SubDir = "grafx2"; else { - Config_SubDir = ".config/grafx2"; - config_parent_dir = getenv("HOME"); + Config_SubDir = ".config/grafx2"; + config_parent_dir = getenv("HOME"); } #endif Portable_Installation_Detected = 0; if (config_parent_dir && config_parent_dir[0]!='\0') { - int size = strlen(config_parent_dir); - strcpy(config_dir, config_parent_dir); + size_t size = strlen(config_parent_dir); + free(config_dir); + len = size + strlen(Config_SubDir) + strlen(PATH_SEPARATOR) + 1; if (config_parent_dir[size-1] != '\\' && config_parent_dir[size-1] != '/') { - strcat(config_dir,PATH_SEPARATOR); - } - strcat(config_dir,Config_SubDir); - if (Directory_exists(config_dir)) - { - // Répertoire trouvé, ok - strcat(config_dir,PATH_SEPARATOR); + len += strlen(PATH_SEPARATOR); + config_dir = malloc(len); + snprintf(config_dir, len, "%s%s%s%s", + config_parent_dir, PATH_SEPARATOR, + Config_SubDir, PATH_SEPARATOR); } else + { + config_dir = malloc(len); + snprintf(config_dir, len, "%s%s%s", + config_parent_dir, + Config_SubDir, PATH_SEPARATOR); + } + if (!Directory_exists(config_dir)) { // Tentative de création - if (!Create_ConfigDirectory(config_dir)) - { - // Réussi - strcat(config_dir,PATH_SEPARATOR); - } - else + if (Create_ConfigDirectory(config_dir) < 0) { // Echec: on se rabat sur le repertoire de l'executable. - strcpy(config_dir,program_dir); Portable_Installation_Detected = 1; + free(config_dir); #if defined(__macosx__) - strcat(config_dir, "../"); + len = strlen(program_dir) + 4; + config_dir = malloc(len); + snprintf(config_dir, len, "%s%s", program_dir, "../"); + #else + config_dir = strdup(program_dir); #endif } } } } + free(filename); + return config_dir; #endif } diff --git a/src/setup.h b/src/setup.h index e37b9e94..874d42a6 100644 --- a/src/setup.h +++ b/src/setup.h @@ -31,16 +31,15 @@ /// /// Determine which directory contains the executable. -/// - IN: Main's argv[0], some platforms need it, some don't. -/// - OUT: Write into program_dir. Trailing / or \ is kept. +/// @param argv0 Main's argv[0], some platforms need it, some don't. +/// @return malloc'ed string. Trailing / or \ is kept. /// Note : in fact this is only used to check for the datafiles and fonts in this same directory. -void Set_program_directory(const char * argv0,char * program_dir); +char * Get_program_directory(const char * argv0); /// /// Determine which directory contains the read-only data. -/// IN: The directory containing the executable -/// OUT: Write into data_dir. Trailing / or \ is kept. -void Set_data_directory(const char * program_dir, char * data_dir); +/// @return malloc'ed string +char * Get_data_directory(const char * program_dir); /// /// Determine which directory should store the user's configuration. @@ -51,19 +50,19 @@ void Set_data_directory(const char * program_dir, char * data_dir); /// to create it ($(HOME)/.grafx2, or %APPDATA%\\GrafX2) /// If it cannot be created, this function will return the executable's /// own directory. -/// IN: The directory containing the executable -/// OUT: Write into config_dir. Trailing / or \ is kept. -void Set_config_directory(const char * program_dir, char * config_dir); +/// @param program_dir The directory containing the executable +/// @return malloc'ed string. Trailing / or \ is kept. +char * Get_config_directory(const char * program_dir); -/// Name of the subdirectory containing fonts, under the data directory (::Set_data_directory()) +/// Name of the subdirectory containing fonts, under the data directory (::Get_data_directory()) #if defined (__MINT__) #define FONTS_SUBDIRECTORY "FONTS" #else #define FONTS_SUBDIRECTORY "fonts" #endif -/// Name of the subdirectory containing fonts, under the data directory (::Set_data_directory()) +/// Name of the subdirectory containing fonts, under the data directory (::Get_data_directory()) #if defined (__MINT__) #define SKINS_SUBDIRECTORY "SKINS" #else