# HG changeset patch # User Matti Hamalainen # Date 1453300805 -7200 # Node ID b256db93cf2549c1ad141144c681c77ccdc8ec4d # Parent 8baec5a454c11913a8062cd3c20081a2e961ffee Initial import of th_file module. diff -r 8baec5a454c1 -r b256db93cf25 th_file.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/th_file.c Wed Jan 20 16:40:05 2016 +0200 @@ -0,0 +1,143 @@ +/* + * File, directory etc helper functions + * Programmed and designed by Matti 'ccr' Hamalainen + * (C) Copyright 2016 Tecnic Software productions (TNSP) + * + * Please read file 'COPYING' for information on license and distribution. + */ +#include "th_file.h" +#include "th_string.h" +#include +//#include +#ifdef TH_PLAT_WINDOWS +# include +# include +#else +//# include +# include +# include +#endif + + +char * th_get_home_dir() +{ +#if defined(TH_PLAT_WINDOWS) + char tmpPath[MAX_PATH]; + if (SHGetFolderPath(NULL, CSIDL_APPDATA | CSIDL_FLAG_CREATE, NULL, 0, tmpPath) == S_OK) + return th_strdup(tmpPath); +#endif + return th_strdup(getenv("HOME")); +} + + +char * th_get_data_dir() +{ +#if defined(TH_PLAT_WINDOWS) + char tmpPath[MAX_PATH]; + if (SHGetFolderPath(NULL, CSIDL_APPDATA | CSIDL_FLAG_CREATE, NULL, 0, tmpPath) == S_OK) + return th_strdup(tmpPath); +#endif + return th_strdup(getenv("HOME")); +} + + +char * th_get_config_dir() +{ +#if defined(TH_PLAT_WINDOWS) + // For Windows, we just use the appdata directory + return th_get_data_dir(); +#elif defined(USE_XDG) + const char *xdgConfigDir = getenv("XDG_CONFIG_HOME"); + + // If XDG is enabled, try the environment variable first + if (xdgConfigDir != NULL && strcmp(xdgConfigDir, "")) + return th_strdup_printf("%s" TH_DIR_SEPARATOR "%s" TH_DIR_SEPARATOR, xdgConfigDir, SET_XDG_CONFIG_DIR); + else + // Nope, try the obvious alternative + return th_strdup_printf("%s" TH_DIR_SEPARATOR ".config" TH_DIR_SEPARATOR "%s" TH_DIR_SEPARATOR, + setHomeDir, SET_XDG_CONFIG_DIR); +#else + // XDG not enabled + return th_get_data_dir(); +#endif +} + + +BOOL th_stat_path(const char *path, int *flags) +{ + *flags = 0; + +#ifdef TH_PLAT_WINDOWS + DWORD attr = GetFileAttributes(path); + + *flags |= (attr & FILE_ATTRIBUTE_DIRECTORY) ? TH_IS_DIR : 0; + *flags |= (attr & FILE_ATTRIBUTE_READONLY) ? 0 : TH_IS_WRITABLE; + *flags |= TH_IS_READABLE; +#else + uid_t id = geteuid(); + struct stat sb; + if (stat(path, &sb) < 0) + return FALSE; + + *flags |= S_ISDIR(sb.st_mode) ? TH_IS_DIR : 0; + *flags |= (id == sb.st_uid && (sb.st_mode & S_IWUSR)) ? TH_IS_WRITABLE : 0; + *flags |= (id == sb.st_uid && (sb.st_mode & S_IRUSR)) ? TH_IS_READABLE : 0; +#endif + + return TRUE; +} + + +BOOL th_mkdir_path(const char *cpath, int mode) +{ + char save, *path = th_strdup(cpath); + size_t start = 0, end; + BOOL res = FALSE; + + // If mode is 0, default to something sensible + if (mode == 0) + mode = 0711; + + // Start creating the directory stucture + do + { + // Split foremost path element out + for (save = 0, end = start; path[end] != 0; end++) + if (path[end] == TH_DIR_SEPARATOR) + { + save = path[end]; + path[end] = 0; + break; + } + + // If the element is there, create it + if (path[start] != 0) + { + int flags; + BOOL exists = th_stat_path(path, &flags); + if (exists && (flags & TH_IS_DIR) == 0) + goto error; + + if (!exists) + { +#ifdef TH_PLAT_WINDOWS + if (!CreateDirectory(path, NULL)) + goto error; +#else + if (mkdir(path, mode) < 0) + goto error; +#endif + } + } + + // Restore separator character and jump to next element + path[end] = save; + start = end + 1; + } while (save != 0); + + res = TRUE; + +error: + th_free(path); + return res; +} diff -r 8baec5a454c1 -r b256db93cf25 th_file.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/th_file.h Wed Jan 20 16:40:05 2016 +0200 @@ -0,0 +1,47 @@ +/* + * File, directory etc helper functions + * Programmed and designed by Matti 'ccr' Hamalainen + * (C) Copyright 2016 Tecnic Software productions (TNSP) + * + * Please read file 'COPYING' for information on license and distribution. + */ +#ifndef TH_FILE_H +#define TH_FILE_H + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "th_util.h" + + +// Platform specific defines +#if defined(TH_PLAT_WINDOWS) +# define TH_DIR_SEPARATOR '\\' +#else +# define TH_DIR_SEPARATOR '/' +#endif + + +// Flags for th_stat_path() +enum +{ + TH_IS_DIR = 0x1000, + TH_IS_SYMLINK = 0x2000, + + TH_IS_WRITABLE = 0x0002, + TH_IS_READABLE = 0x0004, +}; + + +char * th_get_home_dir(); +char * th_get_config_dir(); + +BOOL th_stat_path(const char *path, int *flags); +BOOL th_mkdir_path(const char *cpath, int mode); + + +#ifdef __cplusplus +} +#endif +#endif // TH_FILE_H