/* See LICENSE file for copyright and license details. */ #include "common.h" #ifndef TEST static int add_dirn(char ***dirsp, size_t *countp, size_t *sizep, const char *part1, size_t part1_len, const char *part2, size_t part2_len) { char *dir, **new; size_t i; if (*countp == *sizep) { if (SIZE_MAX / sizeof(**dirsp) - 8) goto enomem; new = realloc(*dirsp, (*sizep + 8) * sizeof(**dirsp)); if (!new) goto enomem; *dirsp = new; *sizep += 8; } dir = malloc(part1_len + part2_len + 1); if (!dir) { enomem: errno = ENOMEM; return -1; } memcpy(dir, part1, part1_len); memcpy(&dir[part1_len], part2, part2_len + 1); for (i = 0; i < *countp; i++) { if (!strcmp(dir, (*dirsp)[i])) { free(dir); return 0; } } (*dirsp)[(*countp)++] = dir; return 0; } static int add_dir(char ***dirsp, size_t *countp, size_t *sizep, const char *part1, const char *part2) { return add_dirn(dirsp, countp, sizep, part1, strlen(part1), part2, strlen(part2)); } static int add_dirs(char ***dirsp, size_t *countp, size_t *sizep, const char *env, const char *part2) { size_t part2_len = strlen(part2); char *p; for (; (p = strchr(env, ':')); env = &p[1]) if (*p != ':') if (add_dirn(dirsp, countp, sizep, env, (size_t)(p - env), part2, part2_len)) return -1; return *env ? add_dirn(dirsp, countp, sizep, env, strlen(env), part2, part2_len) : 0; } int libfonts_get_font_root_dirs(char ***dirsp, size_t *countp, struct libfonts_context *ctx) { const char *env; char **new, *home = NULL; size_t size = 0; const char *env_xdg_data_home = libfonts_getenv__("XDG_DATA_HOME", ctx); const char *env_home = libfonts_getenv__("HOME", ctx); const char *env_xdg_data_dirs = libfonts_getenv__("XDG_DATA_DIRS", ctx); *dirsp = NULL; *countp = 0; env = libfonts_getenv__("LIBFONTS_FONT_DIRS", ctx); if (env && *env && add_dirs(dirsp, countp, &size, env, "")) goto fail; env = env_xdg_data_home; if (env && *env && add_dir(dirsp, countp, &size, env, "/libfonts")) goto fail; env = env_home; if (env && *env && (add_dir(dirsp, countp, &size, env, "/.local/share/libfonts") || add_dir(dirsp, countp, &size, env, "/.libfonts"))) goto fail; home = libfonts_gethome__(ctx); if (home && *home && (add_dir(dirsp, countp, &size, home, "/.local/share/libfonts") || add_dir(dirsp, countp, &size, home, "/.libfonts"))) goto fail; env = env_xdg_data_dirs; if (env && *env && add_dirs(dirsp, countp, &size, env, "/libfonts")) goto fail; if (add_dirs(dirsp, countp, &size, "/usr/local/share", "/libfonts") || add_dirs(dirsp, countp, &size, "/usr/share", "/libfonts")) goto fail; env = env_xdg_data_home; if (env && *env && add_dir(dirsp, countp, &size, env, "/fonts")) goto fail; env = env_home; if (env && *env && (add_dir(dirsp, countp, &size, env, "/.local/share/fonts") || add_dir(dirsp, countp, &size, env, "/.fonts"))) goto fail; if (home && *home && (add_dir(dirsp, countp, &size, home, "/.local/share/fonts") || add_dir(dirsp, countp, &size, home, "/.fonts"))) goto fail; free(home); home = NULL; env = env_xdg_data_dirs; if (env && *env && add_dirs(dirsp, countp, &size, env, "/fonts")) goto fail; if (add_dirs(dirsp, countp, &size, "/usr/local/share", "/fonts") || add_dirs(dirsp, countp, &size, "/usr/share", "/fonts")) goto fail; if (*countp == size) { if (SIZE_MAX / sizeof(**dirsp) - 1) goto enomem; new = realloc(*dirsp, (size + 1) * sizeof(**dirsp)); if (!new) goto enomem; *dirsp = new; } (*dirsp)[*countp] = NULL; return 0; enomem: errno = ENOMEM; fail: if (dirsp) while (*countp) free((*dirsp)[--*countp]); free(*dirsp); free(home); *dirsp = NULL; *countp = 0; return -1; } #else int main(void) { return 0; /* XXX add test */ } #endif