Mercurial > hg > th-libs
view th_file.c @ 777:484853471eaf
Rename th_cfg_add_hexvalue() to th_cfg_add_hex_triplet().
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Sun, 02 Jul 2023 03:19:57 +0300 |
parents | 64af66cae541 |
children | db1a132c7754 |
line wrap: on
line source
/* * File, directory etc helper functions * Programmed and designed by Matti 'ccr' Hamalainen * (C) Copyright 2016-2022 Tecnic Software productions (TNSP) * * Please read file 'COPYING' for information on license and distribution. */ #include "th_file.h" #include "th_string.h" #include <unistd.h> #if defined(TH_PLAT_WINDOWS) # include <shlwapi.h> # include <shfolder.h> #elif defined(TH_PLAT_DOS) # include <sys/stat.h> # include <sys/types.h> #else //# include <sys/wait.h> # include <sys/stat.h> # include <sys/types.h> #endif char * th_get_home_dir(void) { #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); else return th_strdup(""); #elif defined(TH_PLAT_DOS) return th_strdup("C:\\"); #else return th_strdup(getenv("HOME")); #endif } 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); else return th_strdup(""); #elif defined(TH_PLAT_DOS) return th_strdup("C:\\"); #else return th_strdup(getenv("HOME")); #endif } char * th_get_config_dir(void) { #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%c", xdgConfigDir, TH_DIR_SEPARATOR_CHR); } else { // Nope, try the obvious alternative char *data = th_get_data_dir(); char *dir = th_strdup_printf("%s%c%s%c", data, TH_DIR_SEPARATOR_CHR, ".config", TH_DIR_SEPARATOR_CHR); th_free(data); return dir; } #else // XDG not enabled return th_get_data_dir(); #endif } #ifdef TH_PLAT_WINDOWS static uint64_t th_convert_windows_time(FILETIME ftime) { uint64_t value = (((uint64_t) ftime.dwHighDateTime) << 32ULL) | ((uint64_t) ftime.dwLowDateTime); // Naive conversion (1000 ns / 100) * ns - difference_between_win_to_unix_epoch return (value / ((1000 / 100) * 1000 * 1000)) - 11644473600ULL;; } #endif bool th_stat_path(const char *path, th_stat_data *data) { memset(data, 0, sizeof(*data)); #if defined(TH_PLAT_WINDOWS) WIN32_FILE_ATTRIBUTE_DATA fdata; if (!GetFileAttributesExA(path, GetFileExInfoStandard, &fdata)) return false; data->size = (((uint64_t) fdata.nFileSizeHigh) << 32ULL) | ((uint64_t) fdata.nFileSizeLow); data->ctime = th_convert_windows_time(fdata.ftCreationTime); data->atime = th_convert_windows_time(fdata.ftLastAccessTime); data->mtime = th_convert_windows_time(fdata.ftLastWriteTime); data->flags = (fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? TH_IS_DIR : 0; data->flags |= (fdata.dwFileAttributes & FILE_ATTRIBUTE_READONLY) ? 0 : TH_IS_WRITABLE; data->flags |= TH_IS_READABLE; #else #if defined(TH_PLAT_UNIX) uid_t uid = geteuid(); gid_t gid = getegid(); #endif struct stat sb; if (stat(path, &sb) < 0) return false; data->size = sb.st_size; data->ctime = sb.st_ctime; data->atime = sb.st_atime; data->mtime = sb.st_mtime; data->flags = S_ISDIR(sb.st_mode) ? TH_IS_DIR : 0; #if defined(TH_PLAT_UNIX) if ((uid == sb.st_uid && (sb.st_mode & S_IWUSR)) || (gid == sb.st_gid && (sb.st_mode & S_IWGRP)) || (sb.st_mode & S_IWOTH)) data->flags |= TH_IS_WRITABLE; if ((uid == sb.st_uid && (sb.st_mode & S_IRUSR)) || (gid == sb.st_gid && (sb.st_mode & S_IRGRP)) || (sb.st_mode & S_IROTH)) data->flags |= TH_IS_READABLE; #elif defined(TH_PLAT_DOS) data->flags |= TH_IS_READABLE | TH_IS_WRITABLE; #endif #endif return true; } int th_mkdir_path(const char *cpath, const int mode) { char save, *path = th_strdup(cpath); size_t start = 0, end; int res = THERR_OK; if (path == NULL) return THERR_MALLOC; #if defined(TH_PLAT_WINDOWS) (void) mode; #endif // Start creating the directory stucture do { // Split foremost path element out for (save = 0, end = start; path[end] != 0; end++) if (path[end] == '/' || path[end] == '\\') { save = path[end]; path[end] = 0; break; } // If the element is there, create it if (path[start] != 0) { th_stat_data sdata; bool exists = th_stat_path(path, &sdata); if (exists && (sdata.flags & TH_IS_DIR) == 0) { res = THERR_FWRITE; goto out; } if (!exists) { #if defined(TH_PLAT_WINDOWS) if (!CreateDirectory(path, NULL)) #else if (mkdir(path, mode != 0 ? mode : 0711) < 0) #endif { res = th_get_error(); goto out; } } } // Restore separator character and jump to next element path[end] = save; start = end + 1; } while (save != 0); out: th_free(path); return res; }