From cb947bf4149e9d3cc2368476702d87c0d50b9836 Mon Sep 17 00:00:00 2001 From: sisyffe Date: Mon, 1 Jan 2024 18:39:24 +0100 Subject: [PATCH 1/5] Changed the macOS functioning (more modern) --- cfgpath.h | 81 ++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 53 insertions(+), 28 deletions(-) diff --git a/cfgpath.h b/cfgpath.h index f48bb77..80ee3e5 100644 --- a/cfgpath.h +++ b/cfgpath.h @@ -59,8 +59,12 @@ #define PATH_SEPARATOR_STRING "\\" #elif defined(__APPLE__) #define CFGPATH_MAC -#include +#include +#include #include +#include /* PATH_MAX */ +#include /* Apple API */ +#include /* Utility stuff (replace the tilde) */ #define MAX_PATH PATH_MAX #define PATH_SEPARATOR_CHAR '/' #define PATH_SEPARATOR_STRING "/" @@ -154,21 +158,31 @@ static inline void get_user_config_file(char *out, unsigned int maxlen, const ch strcat(out, appname); strcat(out, ".ini"); #elif defined(CFGPATH_MAC) - FSRef ref; - FSFindFolder(kUserDomain, kApplicationSupportFolderType, kCreateFolder, &ref); - char home[MAX_PATH]; - FSRefMakePath(&ref, (UInt8 *)&home, MAX_PATH); - /* first +1 is "/", second is terminating null */ - const char *ext = ".conf"; - if (strlen(home) + 1 + strlen(appname) + strlen(ext) + 1 > maxlen) { - out[0] = 0; + const sysdir_search_path_enumeration_state state = sysdir_start_search_path_enumeration( + SYSDIR_DIRECTORY_APPLICATION_SUPPORT, + SYSDIR_DOMAIN_MASK_USER + ); + if (!sysdir_get_next_search_path_enumeration(state, out)) { + out[0] = 0; return; - } + } - strcpy(out, home); - strcat(out, PATH_SEPARATOR_STRING); - strcat(out, appname); - strcat(out, ext); + // Remove the tilde + glob_t globbuf; + if (glob(out, GLOB_TILDE, NULL, &globbuf) == 0) { + const char *ext = ".conf"; + /* first +1 is "/", second is trailing "/", third is terminating null */ + if (strlen(globbuf.gl_pathv[0]) + 1 + strlen(appname) + strlen(ext) + 1 > maxlen) { + out[0] = 0; + return; + } + + // final copy + strcpy(out, globbuf.gl_pathv[0]); + strcat(out, PATH_SEPARATOR_STRING); + strcat(out, appname); + strcat(out, ext); + } #endif } @@ -265,22 +279,33 @@ static inline void get_user_config_folder(char *out, unsigned int maxlen, const mkdir(out); strcat(out, "\\"); #elif defined(CFGPATH_MAC) - FSRef ref; - FSFindFolder(kUserDomain, kApplicationSupportFolderType, kCreateFolder, &ref); - char home[MAX_PATH]; - FSRefMakePath(&ref, (UInt8 *)&home, MAX_PATH); - /* first +1 is "/", second is trailing "/", third is terminating null */ - if (strlen(home) + 1 + strlen(appname) + 1 + 1 > maxlen) { - out[0] = 0; + const sysdir_search_path_enumeration_state state = sysdir_start_search_path_enumeration( + SYSDIR_DIRECTORY_APPLICATION_SUPPORT, + SYSDIR_DOMAIN_MASK_USER + ); + if (!sysdir_get_next_search_path_enumeration(state, out)) { + out[0] = '\0'; return; - } + } - strcpy(out, home); - strcat(out, PATH_SEPARATOR_STRING); - strcat(out, appname); - /* Make the .config/appname folder if it doesn't already exist */ - mkdir(out, 0755); - strcat(out, PATH_SEPARATOR_STRING); + // Remove the tilde + glob_t globbuf; + if (glob(out, GLOB_TILDE, NULL, &globbuf) == 0) { + /* first +1 is "/", second is trailing "/", third is terminating null */ + if (strlen(globbuf.gl_pathv[0]) + 1 + strlen(appname) + 1 + 1 > maxlen) { + out[0] = '\0'; + return; + } + + // final copy + strcpy(out, globbuf.gl_pathv[0]); + strcat(out, PATH_SEPARATOR_STRING); + strcat(out, appname); + /* Make the config folder if it doesn't already exist */ + mkdir(out, 0755); + strcat(out, PATH_SEPARATOR_STRING); + } + globfree(&globbuf); #endif } From 5b8f0d2b2156de50a0ee8e691e3361e9229479c7 Mon Sep 17 00:00:00 2001 From: sisyffe Date: Mon, 1 Jan 2024 18:43:28 +0100 Subject: [PATCH 2/5] Added basic tests for macos --- .gitignore | 1 + Makefile | 8 ++++++-- test-macos.c | 0 3 files changed, 7 insertions(+), 2 deletions(-) create mode 100644 test-macos.c diff --git a/.gitignore b/.gitignore index 5df9bd6..e4412e6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ test-linux test-win +test-macos diff --git a/Makefile b/Makefile index e1140a6..15fdda6 100644 --- a/Makefile +++ b/Makefile @@ -1,13 +1,17 @@ .PHONY: all check -all: test-linux test-win +all: test-linux test-win test-macos -check: test-linux test-win +check: test-linux test-win test-macos ./test-linux ./test-win + ./test-macos test-linux: test-linux.c cfgpath.h $(CC) -O0 -g -o $@ $< test-win: test-win.c cfgpath.h shlobj.h $(CC) -O0 -g -o $@ $< -I. + +test-macos: test-macos.c cfgpath.h + $(CC) -O0 -g -o $@ $< diff --git a/test-macos.c b/test-macos.c new file mode 100644 index 0000000..e69de29 From 655ac315fb69026a227d63179a2547e0bbde8070 Mon Sep 17 00:00:00 2001 From: sisyffe Date: Mon, 1 Jan 2024 18:51:16 +0100 Subject: [PATCH 3/5] Changed the functionning of the get_user_config_file on macOS tho return a file inside the config foler --- cfgpath.h | 41 ++++++++++++++++------------------------- test-macos.c | 20 ++++++++++++++++++++ 2 files changed, 36 insertions(+), 25 deletions(-) diff --git a/cfgpath.h b/cfgpath.h index 80ee3e5..0a6b0a6 100644 --- a/cfgpath.h +++ b/cfgpath.h @@ -72,6 +72,11 @@ #error cfgpath.h functions have not been implemented for your platform! Please send patches. #endif +static inline void get_user_config_file(char *out, unsigned int maxlen, const char *appname); +static inline void get_user_config_folder(char *out, unsigned int maxlen, const char *appname); +static inline void get_user_data_folder(char *out, unsigned int maxlen, const char *appname); +static inline void get_user_cache_folder(char *out, unsigned int maxlen, const char *appname); + /** Get an absolute path to a single configuration file, specific to this user. * * This function is useful for programs that need only a single configuration @@ -81,7 +86,7 @@ * * Windows: C:\Users\jcitizen\AppData\Roaming\appname.ini * Linux: /home/jcitizen/.config/appname.conf - * Mac: /Users/jcitizen/Library/Application Support/appname.conf + * Mac: /Users/jcitizen/Library/Application Support/appname/appname.conf * * @param out * Buffer to write the path. On return will contain the path, or an empty @@ -158,31 +163,17 @@ static inline void get_user_config_file(char *out, unsigned int maxlen, const ch strcat(out, appname); strcat(out, ".ini"); #elif defined(CFGPATH_MAC) - const sysdir_search_path_enumeration_state state = sysdir_start_search_path_enumeration( - SYSDIR_DIRECTORY_APPLICATION_SUPPORT, - SYSDIR_DOMAIN_MASK_USER - ); - if (!sysdir_get_next_search_path_enumeration(state, out)) { - out[0] = 0; + const char *ext = ".conf"; + get_user_config_folder(out, maxlen, appname); + /* +1 is terminating null */ + if (strlen(out) + strlen(appname) + strlen(ext) + 1 > maxlen) { + out[0] = 0; return; - } - - // Remove the tilde - glob_t globbuf; - if (glob(out, GLOB_TILDE, NULL, &globbuf) == 0) { - const char *ext = ".conf"; - /* first +1 is "/", second is trailing "/", third is terminating null */ - if (strlen(globbuf.gl_pathv[0]) + 1 + strlen(appname) + strlen(ext) + 1 > maxlen) { - out[0] = 0; - return; - } + } - // final copy - strcpy(out, globbuf.gl_pathv[0]); - strcat(out, PATH_SEPARATOR_STRING); - strcat(out, appname); - strcat(out, ext); - } + // final copy + strcat(out, appname); + strcat(out, ext); #endif } @@ -296,7 +287,7 @@ static inline void get_user_config_folder(char *out, unsigned int maxlen, const out[0] = '\0'; return; } - + // final copy strcpy(out, globbuf.gl_pathv[0]); strcat(out, PATH_SEPARATOR_STRING); diff --git a/test-macos.c b/test-macos.c index e69de29..34adff1 100644 --- a/test-macos.c +++ b/test-macos.c @@ -0,0 +1,20 @@ +#include "cfgpath.h" + +#include + +int main() { + char config_folder[MAX_PATH]; + char config_file[MAX_PATH]; + char data_folder[MAX_PATH]; + char cache_folder[MAX_PATH]; + + get_user_config_folder(config_folder, MAX_PATH, "myapp"); + get_user_config_file(config_file, MAX_PATH, "myapp"); + get_user_data_folder(data_folder, MAX_PATH, "myapp"); + get_user_cache_folder(cache_folder, MAX_PATH, "myapp"); + + printf("Config folder: %s\n", strlen(config_folder) ? config_folder : "ERROR"); + printf("Config file: %s\n", strlen(config_file) ? config_file : "ERROR"); + printf("Data folder: %s\n", strlen(data_folder) ? data_folder : "ERROR"); + printf("Cache folder: %s\n", strlen(cache_folder) ? cache_folder : "ERROR"); +} From 92871dc797830ba69f771ef1383e20414a8bd107 Mon Sep 17 00:00:00 2001 From: sisyffe Date: Mon, 1 Jan 2024 19:04:57 +0100 Subject: [PATCH 4/5] Final tweaks: new make target (clean), changed macOS tests --- Makefile | 5 ++++- test-macos.c | 21 ++++++++++++--------- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/Makefile b/Makefile index 15fdda6..3c57c11 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -.PHONY: all check +.PHONY: all check clean all: test-linux test-win test-macos @@ -7,6 +7,9 @@ check: test-linux test-win test-macos ./test-win ./test-macos +clean: + rm -f test-linux test-win test-macos + test-linux: test-linux.c cfgpath.h $(CC) -O0 -g -o $@ $< diff --git a/test-macos.c b/test-macos.c index 34adff1..c57c072 100644 --- a/test-macos.c +++ b/test-macos.c @@ -3,18 +3,21 @@ #include int main() { - char config_folder[MAX_PATH]; - char config_file[MAX_PATH]; - char data_folder[MAX_PATH]; - char cache_folder[MAX_PATH]; + char* config_file = malloc(MAX_PATH * sizeof(char)); + char* config_folder = malloc(MAX_PATH * sizeof(char)); + char* data_folder = malloc(MAX_PATH * sizeof(char)); + char* cache_folder = malloc(MAX_PATH * sizeof(char)); + char* too_small = malloc(10 * sizeof(char)); - get_user_config_folder(config_folder, MAX_PATH, "myapp"); get_user_config_file(config_file, MAX_PATH, "myapp"); + get_user_config_folder(config_folder, MAX_PATH, "myapp"); get_user_data_folder(data_folder, MAX_PATH, "myapp"); get_user_cache_folder(cache_folder, MAX_PATH, "myapp"); + get_user_config_folder(too_small, 10, "myapp"); - printf("Config folder: %s\n", strlen(config_folder) ? config_folder : "ERROR"); - printf("Config file: %s\n", strlen(config_file) ? config_file : "ERROR"); - printf("Data folder: %s\n", strlen(data_folder) ? data_folder : "ERROR"); - printf("Cache folder: %s\n", strlen(cache_folder) ? cache_folder : "ERROR"); + printf("Config file: %s\n", strlen(config_file) ? config_file : "ERROR"); + printf("Config folder: %s\n", strlen(config_folder) ? config_folder : "ERROR"); + printf("Data folder: %s\n", strlen(data_folder) ? data_folder : "ERROR"); + printf("Cache folder: %s\n", strlen(cache_folder) ? cache_folder : "ERROR"); + printf("Should be error: %s\n", strlen(too_small) ? too_small : "ERROR"); } From 4a48955f894a5d1ef292230f33a9e6caacfed572 Mon Sep 17 00:00:00 2001 From: sisyffe Date: Mon, 1 Jan 2024 19:10:54 +0100 Subject: [PATCH 5/5] Added C++ namespace --- cfgpath.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/cfgpath.h b/cfgpath.h index 0a6b0a6..56a093c 100644 --- a/cfgpath.h +++ b/cfgpath.h @@ -72,6 +72,10 @@ #error cfgpath.h functions have not been implemented for your platform! Please send patches. #endif +#ifdef __cplusplus +namespace cfgpath { +#endif + static inline void get_user_config_file(char *out, unsigned int maxlen, const char *appname); static inline void get_user_config_folder(char *out, unsigned int maxlen, const char *appname); static inline void get_user_data_folder(char *out, unsigned int maxlen, const char *appname); @@ -488,4 +492,8 @@ static inline void get_user_cache_folder(char *out, unsigned int maxlen, const c #endif } +#ifdef __cplusplus +} // namespace cfgpath +#endif + #endif /* CFGPATH_H_ */