/** 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* env; char* home, *defVal; env = getenv("HOME"); if (!env || !env[0]) return FALSE; if (!(home = (char*)malloc(strlen(env)+1))) return FALSE; strcpy(home, env); /* Allocate maximum needed for any of the 3 default values */ defVal = (char*)malloc(strlen(home)+ MAX(MAX(sizeof(DefaultRelativeDataHome), sizeof(DefaultRelativeConfigHome)), sizeof(DefaultRelativeCacheHome))); if (!defVal) return FALSE; strcpy(defVal, home); strcat(defVal, DefaultRelativeDataHome); if (!(cache->dataHome = xdgGetEnv("XDG_DATA_HOME", defVal))) return FALSE; defVal[strlen(home)] = 0; strcat(defVal, DefaultRelativeConfigHome); if (!(cache->configHome = xdgGetEnv("XDG_CONFIG_HOME", defVal))) return FALSE; defVal[strlen(home)] = 0; strcat(defVal, DefaultRelativeCacheHome); if (!(cache->cacheHome = xdgGetEnv("XDG_CACHE_HOME", defVal))) return FALSE; free(defVal); free(home); return TRUE; }
/** * Duplicate an environment variable. * 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. * @return The duplicated string or NULL if an error occurs. */ static char* xdgEnvDup(const char *name) { const char *env; env = xdgGetEnv( name ); if (env != NULL) return strdup(env); return NULL; }
/** Duplicate an environment variable. * 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. * @return The duplicated string or NULL if an error occurs. */ static char* xdgEnvDup(const char *name) { const char *env; if ((env = xdgGetEnv(name))) return strdup(env); else return NULL; }
/** 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; }
/** 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; }