/** Update all *Home variables of cache. * This includes xdgCachedData::dataHome, xdgCachedData::configHome and xdgCachedData::cacheHome. * @param cache Data cache to be updated */ static int xdgUpdateHomeDirectories(xdgCachedData* cache) { const char *homeenv; char *value; unsigned int homelen; static const unsigned int extralen = MAX(MAX(sizeof(DefaultRelativeDataHome), sizeof(DefaultRelativeConfigHome)), sizeof(DefaultRelativeCacheHome)); if (!(cache->dataHome = xdgEnvDup("XDG_DATA_HOME")) && errno == ENOMEM) return FALSE; if (!(cache->configHome = xdgEnvDup("XDG_CONFIG_HOME")) && errno == ENOMEM) return FALSE; if (!(cache->cacheHome = xdgEnvDup("XDG_CACHE_HOME")) && errno == ENOMEM) return FALSE; if (!(cache->runtimeDirectory = xdgEnvDup("XDG_RUNTIME_DIR")) && errno == ENOMEM) return FALSE; errno = 0; if (cache->dataHome && cache->configHome && cache->cacheHome) return TRUE; if (!(homeenv = xdgGetEnv("HOME"))) return FALSE; /* Allocate maximum needed for any of the 3 default values */ if (!(value = (char*)malloc((homelen = strlen(homeenv))+extralen))) return FALSE; memcpy(value, homeenv, homelen+1); if (!cache->dataHome) { memcpy(value+homelen, DefaultRelativeDataHome, sizeof(DefaultRelativeDataHome)); cache->dataHome = strdup(value); } if (!cache->configHome) { memcpy(value+homelen, DefaultRelativeConfigHome, sizeof(DefaultRelativeConfigHome)); cache->configHome = strdup(value); } if (!cache->cacheHome) { memcpy(value+homelen, DefaultRelativeCacheHome, sizeof(DefaultRelativeCacheHome)); cache->cacheHome = strdup(value); } free(value); /* free does not change errno, and the prev call *must* have been a strdup, * so errno is already set. */ return cache->dataHome && cache->configHome && cache->cacheHome; }
const char * xdgRuntimeDirectory(xdgHandle *handle) { if (handle) return xdgGetCache(handle)->runtimeDirectory; else return xdgEnvDup("XDG_RUNTIME_DIRECTORY"); }
/** Get a home directory from the environment or a fallback relative to @c \$HOME. * Sets @c errno to @c ENOMEM if unable to allocate duplicate string. * Sets @c errno to @c EINVAL if variable is not set or empty. * @param envname Name of environment variable. * @param relativefallback Path starting with "/" and relative to @c \$HOME to use as fallback. * @param fallbacklength @c strlen(relativefallback). * @return The home directory path or @c NULL of an error occurs. */ static char * xdgGetRelativeHome(const char *envname, const char *relativefallback, unsigned int fallbacklength) { char *relhome; if (!(relhome = xdgEnvDup(envname)) && errno != ENOMEM) { errno = 0; const char *home; unsigned int homelen; if (!(home = xdgGetEnv("HOME"))) return NULL; if (!(relhome = (char*)malloc((homelen = strlen(home))+fallbacklength))) return NULL; memcpy(relhome, home, homelen); memcpy(relhome+homelen, relativefallback, fallbacklength+1); } return relhome; }
/** * Get a home directory from the environment or a fallback relative to @c \$HOME. * Sets @c errno to @c ENOMEM if unable to allocate duplicate string. * Sets @c errno to @c EINVAL if variable is not set or empty. * @param envname Name of environment variable. * @param relativefallback Path starting with "/" and relative to @c \$HOME to use as fallback. * @return The home directory path or @c NULL of an error occurs. */ static char * xdgGetRelativeHome( const char *envname, const char *relativefallback ) { char *relhome; relhome = xdgEnvDup(envname); if ((relhome == NULL) && (errno != ENOMEM)) { errno = 0; const char *home; unsigned int homelen; home = xdgGetEnv( "HOME" ); if (home == NULL) return NULL; homelen = strlen(home); unsigned int fallbacklength; fallbacklength = strlen( relativefallback ); relhome = malloc( homelen + fallbacklength + 1 ); if (relhome == NULL) return NULL; memcpy( relhome, home, homelen ); memcpy( &relhome[ homelen ], relativefallback, fallbacklength + 1 ); relhome[ homelen + fallbacklength ] = '\0'; /* Just in case. */ } return relhome; }