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