1a32e9e42Smrg/* 2a32e9e42Smrg * fontconfig/test/test-bz89617.c 3a32e9e42Smrg * 4a32e9e42Smrg * Copyright © 2000 Keith Packard 5a32e9e42Smrg * Copyright © 2018 Akira TAGOH 6a32e9e42Smrg * 7a32e9e42Smrg * Permission to use, copy, modify, distribute, and sell this software and its 8a32e9e42Smrg * documentation for any purpose is hereby granted without fee, provided that 9a32e9e42Smrg * the above copyright notice appear in all copies and that both that 10a32e9e42Smrg * copyright notice and this permission notice appear in supporting 11a32e9e42Smrg * documentation, and that the name of the author(s) not be used in 12a32e9e42Smrg * advertising or publicity pertaining to distribution of the software without 13a32e9e42Smrg * specific, written prior permission. The authors make no 14a32e9e42Smrg * representations about the suitability of this software for any purpose. It 15a32e9e42Smrg * is provided "as is" without express or implied warranty. 16a32e9e42Smrg * 17a32e9e42Smrg * THE AUTHOR(S) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 18a32e9e42Smrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 19a32e9e42Smrg * EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY SPECIAL, INDIRECT OR 20a32e9e42Smrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 21a32e9e42Smrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 22a32e9e42Smrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 23a32e9e42Smrg * PERFORMANCE OF THIS SOFTWARE. 24a32e9e42Smrg */ 25a32e9e42Smrg#ifdef HAVE_CONFIG_H 26a32e9e42Smrg#include "config.h" 27a32e9e42Smrg#endif 28a4e54154Smrg#include <stdio.h> 29a32e9e42Smrg#include <stdlib.h> 30a4e54154Smrg#include <string.h> 31a32e9e42Smrg#include <dirent.h> 32a4e54154Smrg#include <errno.h> 33a4e54154Smrg#ifdef HAVE_UNISTD_H 34a4e54154Smrg#include <unistd.h> 35a4e54154Smrg#endif 36a32e9e42Smrg#ifndef HAVE_STRUCT_DIRENT_D_TYPE 37a32e9e42Smrg#include <sys/types.h> 38a32e9e42Smrg#include <sys/stat.h> 39a32e9e42Smrg#endif 40a32e9e42Smrg#include <fontconfig/fontconfig.h> 41a32e9e42Smrg 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#endif 54a4e54154Smrg 55a32e9e42Smrg#ifdef HAVE_MKDTEMP 56a32e9e42Smrg#define fc_mkdtemp mkdtemp 57a32e9e42Smrg#else 58a32e9e42Smrgchar * 59a32e9e42Smrgfc_mkdtemp (char *template) 60a32e9e42Smrg{ 61a32e9e42Smrg if (!mktemp (template) || mkdir (template, 0700)) 62a32e9e42Smrg return NULL; 63a32e9e42Smrg 64a32e9e42Smrg return template; 65a32e9e42Smrg} 66a32e9e42Smrg#endif 67a32e9e42Smrg 68a32e9e42SmrgFcBool 69a32e9e42Smrgmkdir_p (const char *dir) 70a32e9e42Smrg{ 71a32e9e42Smrg char *parent; 72a32e9e42Smrg FcBool ret; 73a32e9e42Smrg 74a32e9e42Smrg if (strlen (dir) == 0) 75a32e9e42Smrg return FcFalse; 76a32e9e42Smrg parent = (char *) FcStrDirname ((const FcChar8 *) dir); 77a32e9e42Smrg if (!parent) 78a32e9e42Smrg return FcFalse; 79a32e9e42Smrg if (access (parent, F_OK) == 0) 80a32e9e42Smrg ret = mkdir (dir, 0755) == 0 && chmod (dir, 0755) == 0; 81a32e9e42Smrg else if (access (parent, F_OK) == -1) 82a32e9e42Smrg ret = mkdir_p (parent) && (mkdir (dir, 0755) == 0) && chmod (dir, 0755) == 0; 83a32e9e42Smrg else 84a32e9e42Smrg ret = FcFalse; 85a32e9e42Smrg free (parent); 86a32e9e42Smrg 87a32e9e42Smrg return ret; 88a32e9e42Smrg} 89a32e9e42Smrg 90a32e9e42SmrgFcBool 91a32e9e42Smrgunlink_dirs (const char *dir) 92a32e9e42Smrg{ 93a32e9e42Smrg DIR *d = opendir (dir); 94a32e9e42Smrg struct dirent *e; 95a32e9e42Smrg size_t len = strlen (dir); 96a32e9e42Smrg char *n = NULL; 97a32e9e42Smrg FcBool ret = FcTrue; 98a32e9e42Smrg#ifndef HAVE_STRUCT_DIRENT_D_TYPE 99a32e9e42Smrg struct stat statb; 100a32e9e42Smrg#endif 101a32e9e42Smrg 102a32e9e42Smrg if (!d) 103a32e9e42Smrg return FcFalse; 104a32e9e42Smrg while ((e = readdir (d)) != NULL) 105a32e9e42Smrg { 106a32e9e42Smrg size_t l; 107a32e9e42Smrg 108a32e9e42Smrg if (strcmp (e->d_name, ".") == 0 || 109a32e9e42Smrg strcmp (e->d_name, "..") == 0) 110a32e9e42Smrg continue; 111a32e9e42Smrg l = strlen (e->d_name) + 1; 112a32e9e42Smrg if (n) 113a32e9e42Smrg free (n); 114a32e9e42Smrg n = malloc (l + len + 1); 115a32e9e42Smrg if (!n) 116a32e9e42Smrg { 117a32e9e42Smrg ret = FcFalse; 118a32e9e42Smrg break; 119a32e9e42Smrg } 120a32e9e42Smrg strcpy (n, dir); 121a32e9e42Smrg n[len] = FC_DIR_SEPARATOR; 122a32e9e42Smrg strcpy (&n[len + 1], e->d_name); 123a32e9e42Smrg#ifdef HAVE_STRUCT_DIRENT_D_TYPE 124a32e9e42Smrg if (e->d_type == DT_DIR) 125a32e9e42Smrg#else 126a32e9e42Smrg if (stat (n, &statb) == -1) 127a32e9e42Smrg { 128a32e9e42Smrg fprintf (stderr, "E: %s\n", n); 129a32e9e42Smrg ret = FcFalse; 130a32e9e42Smrg break; 131a32e9e42Smrg } 132a32e9e42Smrg if (S_ISDIR (statb.st_mode)) 133a32e9e42Smrg#endif 134a32e9e42Smrg { 135a32e9e42Smrg if (!unlink_dirs (n)) 136a32e9e42Smrg { 137a32e9e42Smrg fprintf (stderr, "E: %s\n", n); 138a32e9e42Smrg ret = FcFalse; 139a32e9e42Smrg break; 140a32e9e42Smrg } 141a32e9e42Smrg } 142a32e9e42Smrg else 143a32e9e42Smrg { 144a32e9e42Smrg if (unlink (n) == -1) 145a32e9e42Smrg { 146a32e9e42Smrg fprintf (stderr, "E: %s\n", n); 147a32e9e42Smrg ret = FcFalse; 148a32e9e42Smrg break; 149a32e9e42Smrg } 150a32e9e42Smrg } 151a32e9e42Smrg } 152a32e9e42Smrg if (n) 153a32e9e42Smrg free (n); 154a32e9e42Smrg closedir (d); 155a32e9e42Smrg 156a32e9e42Smrg if (rmdir (dir) == -1) 157a32e9e42Smrg { 158a32e9e42Smrg fprintf (stderr, "E: %s\n", dir); 159a32e9e42Smrg return FcFalse; 160a32e9e42Smrg } 161a32e9e42Smrg 162a32e9e42Smrg return ret; 163a32e9e42Smrg} 164a32e9e42Smrg 165a32e9e42Smrgint 166a32e9e42Smrgmain (void) 167a32e9e42Smrg{ 168a4e54154Smrg FcChar8 *fontdir = NULL, *cachedir = NULL; 169a32e9e42Smrg char *basedir, template[512] = "/tmp/bz106632-XXXXXX"; 170a32e9e42Smrg char cmd[512]; 171a32e9e42Smrg FcConfig *config; 172a4e54154Smrg const FcChar8 *tconf = (const FcChar8 *) "<fontconfig>\n" 173a32e9e42Smrg " <dir>%s</dir>\n" 174a32e9e42Smrg " <cachedir>%s</cachedir>\n" 175a32e9e42Smrg "</fontconfig>\n"; 176a32e9e42Smrg char conf[1024]; 177a32e9e42Smrg int ret = 0; 178a32e9e42Smrg FcFontSet *fs; 179a32e9e42Smrg FcPattern *pat; 180a32e9e42Smrg 181a32e9e42Smrg fprintf (stderr, "D: Creating tmp dir\n"); 182a32e9e42Smrg basedir = fc_mkdtemp (template); 183a32e9e42Smrg if (!basedir) 184a32e9e42Smrg { 185a32e9e42Smrg fprintf (stderr, "%s: %s\n", template, strerror (errno)); 186a32e9e42Smrg goto bail; 187a32e9e42Smrg } 188a4e54154Smrg fontdir = FcStrBuildFilename ((const FcChar8 *) basedir, (const FcChar8 *) "fonts", NULL); 189a4e54154Smrg cachedir = FcStrBuildFilename ((const FcChar8 *) basedir, (const FcChar8 *) "cache", NULL); 190a32e9e42Smrg fprintf (stderr, "D: Creating %s\n", fontdir); 191a4e54154Smrg mkdir_p ((const char *) fontdir); 192a32e9e42Smrg fprintf (stderr, "D: Creating %s\n", cachedir); 193a4e54154Smrg mkdir_p ((const char *) cachedir); 194a32e9e42Smrg 195a32e9e42Smrg fprintf (stderr, "D: Copying %s to %s\n", FONTFILE, fontdir); 196a4e54154Smrg snprintf (cmd, 512, "sleep 1; cp -a %s %s; sleep 1", FONTFILE, fontdir); 197a4e54154Smrg (void) system (cmd); 198a32e9e42Smrg 199a32e9e42Smrg fprintf (stderr, "D: Loading a config\n"); 200a4e54154Smrg snprintf (conf, 1024, (const char *) tconf, fontdir, cachedir); 201a32e9e42Smrg config = FcConfigCreate (); 202a4e54154Smrg if (!FcConfigParseAndLoadFromMemory (config, (const FcChar8 *) conf, FcTrue)) 203a32e9e42Smrg { 204a32e9e42Smrg printf ("E: Unable to load config\n"); 205a32e9e42Smrg ret = 1; 206a32e9e42Smrg goto bail; 207a32e9e42Smrg } 208a32e9e42Smrg if (!FcConfigBuildFonts (config)) 209a32e9e42Smrg { 210a32e9e42Smrg printf ("E: unable to build fonts\n"); 211a32e9e42Smrg ret = 1; 212a32e9e42Smrg goto bail; 213a32e9e42Smrg } 214a32e9e42Smrg fprintf (stderr, "D: Obtaining fonts information\n"); 215a32e9e42Smrg pat = FcPatternCreate (); 216a32e9e42Smrg fs = FcFontList (config, pat, NULL); 217a32e9e42Smrg FcPatternDestroy (pat); 218a32e9e42Smrg if (!fs || fs->nfont != 1) 219a32e9e42Smrg { 220a32e9e42Smrg printf ("E: Unexpected the number of fonts: %d\n", !fs ? -1 : fs->nfont); 221a32e9e42Smrg ret = 1; 222a32e9e42Smrg goto bail; 223a32e9e42Smrg } 224a4e54154Smrg FcFontSetDestroy (fs); 225a32e9e42Smrg fprintf (stderr, "D: Removing %s\n", fontdir); 226a4e54154Smrg snprintf (cmd, 512, "sleep 1; rm -f %s%s*; sleep 1", fontdir, FC_DIR_SEPARATOR_S); 227a4e54154Smrg (void) system (cmd); 228a32e9e42Smrg fprintf (stderr, "D: Reinitializing\n"); 229a4e54154Smrg if (FcConfigUptoDate(config)) 230a32e9e42Smrg { 231a4e54154Smrg fprintf (stderr, "E: Config reports up-to-date\n"); 232a32e9e42Smrg ret = 2; 233a32e9e42Smrg goto bail; 234a32e9e42Smrg } 235a4e54154Smrg if (!FcInitReinitialize ()) 236a4e54154Smrg { 237a4e54154Smrg fprintf (stderr, "E: Unable to reinitialize\n"); 238a4e54154Smrg ret = 3; 239a4e54154Smrg goto bail; 240a4e54154Smrg } 241a32e9e42Smrg if (FcConfigGetCurrent () == config) 242a32e9e42Smrg { 243a32e9e42Smrg fprintf (stderr, "E: config wasn't reloaded\n"); 244a32e9e42Smrg ret = 3; 245a32e9e42Smrg goto bail; 246a32e9e42Smrg } 247a4e54154Smrg FcConfigDestroy (config); 248a4e54154Smrg 249a32e9e42Smrg config = FcConfigCreate (); 250a4e54154Smrg if (!FcConfigParseAndLoadFromMemory (config, (const FcChar8 *) conf, FcTrue)) 251a32e9e42Smrg { 252a32e9e42Smrg printf ("E: Unable to load config again\n"); 253a32e9e42Smrg ret = 4; 254a32e9e42Smrg goto bail; 255a32e9e42Smrg } 256a32e9e42Smrg if (!FcConfigBuildFonts (config)) 257a32e9e42Smrg { 258a32e9e42Smrg printf ("E: unable to build fonts again\n"); 259a32e9e42Smrg ret = 5; 260a32e9e42Smrg goto bail; 261a32e9e42Smrg } 262a32e9e42Smrg fprintf (stderr, "D: Obtaining fonts information again\n"); 263a32e9e42Smrg pat = FcPatternCreate (); 264a32e9e42Smrg fs = FcFontList (config, pat, NULL); 265a32e9e42Smrg FcPatternDestroy (pat); 266a32e9e42Smrg if (!fs || fs->nfont != 0) 267a32e9e42Smrg { 268a32e9e42Smrg printf ("E: Unexpected the number of fonts: %d\n", !fs ? -1 : fs->nfont); 269a32e9e42Smrg ret = 1; 270a32e9e42Smrg goto bail; 271a32e9e42Smrg } 272a4e54154Smrg FcFontSetDestroy (fs); 273a32e9e42Smrg fprintf (stderr, "D: Copying %s to %s\n", FONTFILE, fontdir); 274a4e54154Smrg snprintf (cmd, 512, "sleep 1; cp -a %s %s; sleep 1", FONTFILE, fontdir); 275a4e54154Smrg (void) system (cmd); 276a32e9e42Smrg fprintf (stderr, "D: Reinitializing\n"); 277a4e54154Smrg if (FcConfigUptoDate(config)) 278a4e54154Smrg { 279a4e54154Smrg fprintf (stderr, "E: Config up-to-date after addition\n"); 280a4e54154Smrg ret = 3; 281a4e54154Smrg goto bail; 282a4e54154Smrg } 283a4e54154Smrg if (!FcInitReinitialize ()) 284a32e9e42Smrg { 285a32e9e42Smrg fprintf (stderr, "E: Unable to reinitialize\n"); 286a32e9e42Smrg ret = 2; 287a32e9e42Smrg goto bail; 288a32e9e42Smrg } 289a32e9e42Smrg if (FcConfigGetCurrent () == config) 290a32e9e42Smrg { 291a32e9e42Smrg fprintf (stderr, "E: config wasn't reloaded\n"); 292a32e9e42Smrg ret = 3; 293a32e9e42Smrg goto bail; 294a32e9e42Smrg } 295a4e54154Smrg FcConfigDestroy (config); 296a4e54154Smrg 297a32e9e42Smrg config = FcConfigCreate (); 298a4e54154Smrg if (!FcConfigParseAndLoadFromMemory (config, (const FcChar8 *) conf, FcTrue)) 299a32e9e42Smrg { 300a32e9e42Smrg printf ("E: Unable to load config again\n"); 301a32e9e42Smrg ret = 4; 302a32e9e42Smrg goto bail; 303a32e9e42Smrg } 304a32e9e42Smrg if (!FcConfigBuildFonts (config)) 305a32e9e42Smrg { 306a32e9e42Smrg printf ("E: unable to build fonts again\n"); 307a32e9e42Smrg ret = 5; 308a32e9e42Smrg goto bail; 309a32e9e42Smrg } 310a32e9e42Smrg fprintf (stderr, "D: Obtaining fonts information\n"); 311a32e9e42Smrg pat = FcPatternCreate (); 312a32e9e42Smrg fs = FcFontList (config, pat, NULL); 313a32e9e42Smrg FcPatternDestroy (pat); 314a32e9e42Smrg if (!fs || fs->nfont != 1) 315a32e9e42Smrg { 316a32e9e42Smrg printf ("E: Unexpected the number of fonts: %d\n", !fs ? -1 : fs->nfont); 317a32e9e42Smrg ret = 1; 318a32e9e42Smrg goto bail; 319a32e9e42Smrg } 320a4e54154Smrg FcFontSetDestroy (fs); 321a4e54154Smrg FcConfigDestroy (config); 322a32e9e42Smrg 323a32e9e42Smrgbail: 324a32e9e42Smrg fprintf (stderr, "Cleaning up\n"); 325a4e54154Smrg if (basedir) 326a4e54154Smrg unlink_dirs (basedir); 327a32e9e42Smrg if (fontdir) 328a32e9e42Smrg FcStrFree (fontdir); 329a32e9e42Smrg if (cachedir) 330a32e9e42Smrg FcStrFree (cachedir); 331a32e9e42Smrg 332a32e9e42Smrg return ret; 333a32e9e42Smrg} 334