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