1a4e54154Smrg/* 2a4e54154Smrg * fontconfig/test/test-issue107.c 3a4e54154Smrg * 4a4e54154Smrg * Copyright © 2000 Keith Packard 5a4e54154Smrg * Copyright © 2018 Akira TAGOH 6a4e54154Smrg * 7a4e54154Smrg * Permission to use, copy, modify, distribute, and sell this software and its 8a4e54154Smrg * documentation for any purpose is hereby granted without fee, provided that 9a4e54154Smrg * the above copyright notice appear in all copies and that both that 10a4e54154Smrg * copyright notice and this permission notice appear in supporting 11a4e54154Smrg * documentation, and that the name of the author(s) not be used in 12a4e54154Smrg * advertising or publicity pertaining to distribution of the software without 13a4e54154Smrg * specific, written prior permission. The authors make no 14a4e54154Smrg * representations about the suitability of this software for any purpose. It 15a4e54154Smrg * is provided "as is" without express or implied warranty. 16a4e54154Smrg * 17a4e54154Smrg * THE AUTHOR(S) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 18a4e54154Smrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 19a4e54154Smrg * EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY SPECIAL, INDIRECT OR 20a4e54154Smrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 21a4e54154Smrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 22a4e54154Smrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 23a4e54154Smrg * PERFORMANCE OF THIS SOFTWARE. 24a4e54154Smrg */ 25a4e54154Smrg#ifdef HAVE_CONFIG_H 26a4e54154Smrg#include "config.h" 27a4e54154Smrg#endif 28a4e54154Smrg#include <stdio.h> 29a4e54154Smrg#include <stdlib.h> 30a4e54154Smrg#include <string.h> 31a4e54154Smrg#include <dirent.h> 32a4e54154Smrg#include <errno.h> 33a4e54154Smrg#ifdef HAVE_UNISTD_H 34a4e54154Smrg#include <unistd.h> 35a4e54154Smrg#endif 36a4e54154Smrg#ifndef HAVE_STRUCT_DIRENT_D_TYPE 37a4e54154Smrg#include <sys/types.h> 38a4e54154Smrg#include <sys/stat.h> 39a4e54154Smrg#endif 40a4e54154Smrg#include <fontconfig/fontconfig.h> 41a4e54154Smrg 42a4e54154Smrg#ifdef _WIN32 43a4e54154Smrg# define FC_DIR_SEPARATOR '\\' 44a4e54154Smrg# define FC_DIR_SEPARATOR_S "\\" 45a4e54154Smrg#else 46a4e54154Smrg# define FC_DIR_SEPARATOR '/' 47a4e54154Smrg# define FC_DIR_SEPARATOR_S "/" 48a4e54154Smrg#endif 49a4e54154Smrg 50a4e54154Smrg#ifdef _WIN32 51a4e54154Smrg#include <direct.h> 52a4e54154Smrg#define mkdir(path,mode) _mkdir(path) 53a4e54154Smrg 54a4e54154Smrgint 55a4e54154Smrgsetenv(const char *name, const char *value, int o) 56a4e54154Smrg{ 57a4e54154Smrg size_t len = strlen(name) + strlen(value) + 1; 58a4e54154Smrg char *s = malloc(len+1); 59a4e54154Smrg int ret; 60a4e54154Smrg 61a4e54154Smrg snprintf(s, len, "%s=%s", name, value); 62a4e54154Smrg ret = _putenv(s); 63a4e54154Smrg free(s); 64a4e54154Smrg return ret; 65a4e54154Smrg} 66a4e54154Smrg#endif 67a4e54154Smrg 68a4e54154Smrgextern FcChar8 *FcConfigRealFilename (FcConfig *, FcChar8 *); 69a4e54154Smrg 70a4e54154Smrg#ifdef HAVE_MKDTEMP 71a4e54154Smrg#define fc_mkdtemp mkdtemp 72a4e54154Smrg#else 73a4e54154Smrgchar * 74a4e54154Smrgfc_mkdtemp (char *template) 75a4e54154Smrg{ 76a4e54154Smrg if (!mktemp (template) || mkdir (template, 0700)) 77a4e54154Smrg return NULL; 78a4e54154Smrg 79a4e54154Smrg return template; 80a4e54154Smrg} 81a4e54154Smrg#endif 82a4e54154Smrg 83a4e54154SmrgFcBool 84a4e54154Smrgmkdir_p (const char *dir) 85a4e54154Smrg{ 86a4e54154Smrg char *parent; 87a4e54154Smrg FcBool ret; 88a4e54154Smrg 89a4e54154Smrg if (strlen (dir) == 0) 90a4e54154Smrg return FcFalse; 91a4e54154Smrg parent = (char *) FcStrDirname ((const FcChar8 *) dir); 92a4e54154Smrg if (!parent) 93a4e54154Smrg return FcFalse; 94a4e54154Smrg if (access (parent, F_OK) == 0) 95a4e54154Smrg ret = mkdir (dir, 0755) == 0 && chmod (dir, 0755) == 0; 96a4e54154Smrg else if (access (parent, F_OK) == -1) 97a4e54154Smrg ret = mkdir_p (parent) && (mkdir (dir, 0755) == 0) && chmod (dir, 0755) == 0; 98a4e54154Smrg else 99a4e54154Smrg ret = FcFalse; 100a4e54154Smrg free (parent); 101a4e54154Smrg 102a4e54154Smrg return ret; 103a4e54154Smrg} 104a4e54154Smrg 105a4e54154SmrgFcBool 106a4e54154Smrgunlink_dirs (const char *dir) 107a4e54154Smrg{ 108a4e54154Smrg DIR *d = opendir (dir); 109a4e54154Smrg struct dirent *e; 110a4e54154Smrg size_t len = strlen (dir); 111a4e54154Smrg char *n = NULL; 112a4e54154Smrg FcBool ret = FcTrue; 113a4e54154Smrg#ifndef HAVE_STRUCT_DIRENT_D_TYPE 114a4e54154Smrg struct stat statb; 115a4e54154Smrg#endif 116a4e54154Smrg 117a4e54154Smrg if (!d) 118a4e54154Smrg return FcFalse; 119a4e54154Smrg while ((e = readdir (d)) != NULL) 120a4e54154Smrg { 121a4e54154Smrg size_t l; 122a4e54154Smrg 123a4e54154Smrg if (strcmp (e->d_name, ".") == 0 || 124a4e54154Smrg strcmp (e->d_name, "..") == 0) 125a4e54154Smrg continue; 126a4e54154Smrg l = strlen (e->d_name) + 1; 127a4e54154Smrg if (n) 128a4e54154Smrg free (n); 129a4e54154Smrg n = malloc (l + len + 1); 130a4e54154Smrg if (!n) 131a4e54154Smrg { 132a4e54154Smrg ret = FcFalse; 133a4e54154Smrg break; 134a4e54154Smrg } 135a4e54154Smrg strcpy (n, dir); 136a4e54154Smrg n[len] = FC_DIR_SEPARATOR; 137a4e54154Smrg strcpy (&n[len + 1], e->d_name); 138a4e54154Smrg#ifdef HAVE_STRUCT_DIRENT_D_TYPE 139a4e54154Smrg if (e->d_type == DT_DIR) 140a4e54154Smrg#else 141a4e54154Smrg if (stat (n, &statb) == -1) 142a4e54154Smrg { 143a4e54154Smrg fprintf (stderr, "E: %s\n", n); 144a4e54154Smrg ret = FcFalse; 145a4e54154Smrg break; 146a4e54154Smrg } 147a4e54154Smrg if (S_ISDIR (statb.st_mode)) 148a4e54154Smrg#endif 149a4e54154Smrg { 150a4e54154Smrg if (!unlink_dirs (n)) 151a4e54154Smrg { 152a4e54154Smrg fprintf (stderr, "E: %s\n", n); 153a4e54154Smrg ret = FcFalse; 154a4e54154Smrg break; 155a4e54154Smrg } 156a4e54154Smrg } 157a4e54154Smrg else 158a4e54154Smrg { 159a4e54154Smrg if (unlink (n) == -1) 160a4e54154Smrg { 161a4e54154Smrg fprintf (stderr, "E: %s\n", n); 162a4e54154Smrg ret = FcFalse; 163a4e54154Smrg break; 164a4e54154Smrg } 165a4e54154Smrg } 166a4e54154Smrg } 167a4e54154Smrg if (n) 168a4e54154Smrg free (n); 169a4e54154Smrg closedir (d); 170a4e54154Smrg 171a4e54154Smrg if (rmdir (dir) == -1) 172a4e54154Smrg { 173a4e54154Smrg fprintf (stderr, "E: %s\n", dir); 174a4e54154Smrg return FcFalse; 175a4e54154Smrg } 176a4e54154Smrg 177a4e54154Smrg return ret; 178a4e54154Smrg} 179a4e54154Smrg 180a4e54154Smrgint 181a4e54154Smrgmain(void) 182a4e54154Smrg{ 183a4e54154Smrg FcConfig *cfg = FcConfigCreate (); 184a4e54154Smrg char *basedir = NULL, template[512] = "/tmp/fc107-XXXXXX"; 185a4e54154Smrg char *sysroot = NULL, systempl[512] = "/tmp/fc107-XXXXXX"; 186a4e54154Smrg FcChar8 *d = NULL, *dd = NULL; 187a4e54154Smrg FcCache *c = NULL; 188a4e54154Smrg const FcChar8 *doc = (const FcChar8 *) "" 189a4e54154Smrg "<fontconfig>\n" 190a4e54154Smrg " <dir>%s</dir>\n" 191a4e54154Smrg "</fontconfig>\n" 192a4e54154Smrg ""; 193a4e54154Smrg int retval = 0; 194a4e54154Smrg size_t len; 195a4e54154Smrg 196a4e54154Smrg retval++; 197a4e54154Smrg basedir = fc_mkdtemp (template); 198a4e54154Smrg if (!basedir) 199a4e54154Smrg { 200a4e54154Smrg fprintf (stderr, "%s: %s\n", template, strerror (errno)); 201a4e54154Smrg goto bail; 202a4e54154Smrg } 203a4e54154Smrg retval++; 204a4e54154Smrg sysroot = fc_mkdtemp (systempl); 205a4e54154Smrg if (!sysroot) 206a4e54154Smrg { 207a4e54154Smrg fprintf (stderr, "%s: %s\n", systempl, strerror (errno)); 208a4e54154Smrg goto bail; 209a4e54154Smrg } 210a4e54154Smrg retval++; 211a4e54154Smrg fprintf (stderr, "D: Creating %s\n", basedir); 212a4e54154Smrg mkdir_p (basedir); 213a4e54154Smrg len = strlen ((const char *) doc) + strlen (basedir) + 1; 214a4e54154Smrg dd = malloc (len); 215a4e54154Smrg snprintf ((char *) dd, len, (char *) doc, basedir); 216a4e54154Smrg if (!FcConfigParseAndLoadFromMemory (cfg, dd, FcFalse)) 217a4e54154Smrg { 218a4e54154Smrg fprintf (stderr, "%s: Unable to load a config\n", basedir); 219a4e54154Smrg goto bail; 220a4e54154Smrg } 221a4e54154Smrg sleep (1); 222a4e54154Smrg c = FcDirCacheRead ((const FcChar8 *) basedir, FcFalse, cfg); 223a4e54154Smrg FcDirCacheUnload (c); 224a4e54154Smrg sleep (1); 225a4e54154Smrg retval++; 226a4e54154Smrg if (!FcConfigUptoDate (cfg)) 227a4e54154Smrg { 228a4e54154Smrg fprintf (stderr, "updated. need to reload.\n"); 229a4e54154Smrg goto bail; 230a4e54154Smrg } 231a4e54154Smrg setenv ("FONTCONFIG_SYSROOT", sysroot, 1); 232a4e54154Smrg fprintf (stderr, "D: Creating %s\n", sysroot); 233a4e54154Smrg mkdir_p (sysroot); 234a4e54154Smrg retval++; 235a4e54154Smrg d = FcStrBuildFilename ((const FcChar8 *) sysroot, basedir, NULL); 236a4e54154Smrg fprintf (stderr, "D: Creating %s\n", d); 237a4e54154Smrg mkdir_p ((const char *) d); 238a4e54154Smrg free (d); 239a4e54154Smrg retval++; 240a4e54154Smrg free (dd); 241a4e54154Smrg len = strlen ((const char *) doc) + strlen (basedir) + 1; 242a4e54154Smrg dd = malloc (len); 243a4e54154Smrg snprintf ((char *) dd, len, (char *) doc, basedir); 244a4e54154Smrg if (!FcConfigParseAndLoadFromMemory (cfg, dd, FcFalse)) 245a4e54154Smrg { 246a4e54154Smrg fprintf (stderr, "%s: Unable to load a config\n", basedir); 247a4e54154Smrg goto bail; 248a4e54154Smrg } 249a4e54154Smrg sleep (1); 250a4e54154Smrg c = FcDirCacheRead ((const FcChar8 *) basedir, FcFalse, cfg); 251a4e54154Smrg FcDirCacheUnload (c); 252a4e54154Smrg sleep (1); 253a4e54154Smrg retval++; 254a4e54154Smrg if (!FcConfigUptoDate (cfg)) 255a4e54154Smrg { 256a4e54154Smrg fprintf (stderr, "updated. need to reload (sysroot)\n"); 257a4e54154Smrg goto bail; 258a4e54154Smrg } 259a4e54154Smrg retval = 0; 260a4e54154Smrgbail: 261a4e54154Smrg fprintf (stderr, "Cleaning up\n"); 262a4e54154Smrg if (basedir) 263a4e54154Smrg unlink_dirs (basedir); 264a4e54154Smrg if (sysroot) 265a4e54154Smrg unlink_dirs (sysroot); 266a4e54154Smrg if (dd) 267a4e54154Smrg free (dd); 268a4e54154Smrg FcConfigDestroy (cfg); 269a4e54154Smrg 270a4e54154Smrg return retval; 271a4e54154Smrg} 272