test-migration.c revision 953daeba
1/*
2 * fontconfig/test/test-migration.c
3 *
4 * Copyright © 2000 Keith Packard
5 * Copyright © 2013 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#include <stdio.h>
26#include <stdlib.h>
27#include <string.h>
28#include <unistd.h>
29#include <sys/types.h>
30#include <dirent.h>
31#ifndef HAVE_STRUCT_DIRENT_D_TYPE
32#include <sys/types.h>
33#include <sys/stat.h>
34#include <unistd.h>
35#endif
36#include <fontconfig/fontconfig.h>
37
38#ifdef HAVE_MKDTEMP
39#define fc_mkdtemp	mkdtemp
40#else
41char *
42fc_mkdtemp (char *template)
43{
44    if (!mktemp (template) || mkdir (template, 0700))
45	return NULL;
46
47    return template;
48}
49#endif
50
51FcBool
52mkdir_p(const char *dir)
53{
54    char *parent;
55    FcBool ret;
56
57    if (strlen (dir) == 0)
58	return FcFalse;
59    parent = (char *) FcStrDirname ((const FcChar8 *)dir);
60    if (!parent)
61	return FcFalse;
62    if (access (parent, F_OK) == 0)
63	ret = mkdir (dir, 0755) == 0 && chmod (dir, 0755) == 0;
64    else if (access (parent, F_OK) == -1)
65	ret = mkdir_p (parent) && (mkdir (dir, 0755) == 0) && chmod (dir, 0755) == 0;
66    else
67	ret = FcFalse;
68    free (parent);
69
70    return ret;
71}
72
73FcBool
74unlink_dirs(const char *dir)
75{
76    DIR *d = opendir (dir);
77    struct dirent *e;
78    size_t len = strlen (dir);
79    char *n = NULL;
80    FcBool ret = FcTrue;
81#ifndef HAVE_STRUCT_DIRENT_D_TYPE
82    struct stat statb;
83#endif
84
85    if (!d)
86	return FcFalse;
87    while ((e = readdir(d)) != NULL)
88    {
89	size_t l;
90
91	if (strcmp (e->d_name, ".") == 0 ||
92	    strcmp (e->d_name, "..") == 0)
93	    continue;
94	l = strlen (e->d_name) + 1;
95	if (n)
96	    free (n);
97	n = malloc (l + len + 1);
98	strcpy (n, dir);
99	n[len] = '/';
100	strcpy (&n[len + 1], e->d_name);
101#ifdef HAVE_STRUCT_DIRENT_D_TYPE
102	if (e->d_type == DT_DIR)
103#else
104	if (stat (n, &statb) == -1)
105	{
106		fprintf (stderr, "E: %s\n", n);
107		ret = FcFalse;
108		break;
109	}
110	if (S_ISDIR (statb.st_mode))
111#endif
112	{
113	    if (!unlink_dirs (n))
114	    {
115		fprintf (stderr, "E: %s\n", n);
116		ret = FcFalse;
117		break;
118	    }
119	}
120	else
121	{
122	    if (unlink (n) == -1)
123	    {
124		fprintf (stderr, "E: %s\n", n);
125		ret = FcFalse;
126		break;
127	    }
128	}
129    }
130    if (n)
131	free (n);
132    closedir (d);
133
134    if (rmdir (dir) == -1)
135    {
136	fprintf (stderr, "E: %s\n", dir);
137	return FcFalse;
138    }
139
140    return ret;
141}
142
143int
144main(void)
145{
146    char template[32] = "fontconfig-XXXXXXXX";
147    char *tmp = fc_mkdtemp (template);
148    size_t len = strlen (tmp), xlen, dlen;
149    char xdg[256], confd[256], fn[256], nfn[256], ud[256], nud[256];
150    int ret = -1;
151    FILE *fp;
152    char *content = "<fontconfig></fontconfig>";
153
154    strcpy (xdg, tmp);
155    strcpy (&xdg[len], "/.config");
156    setenv ("HOME", tmp, 1);
157    setenv ("XDG_CONFIG_HOME", xdg, 1);
158    xlen = strlen (xdg);
159    strcpy (confd, xdg);
160    strcpy (&confd[xlen], "/fontconfig");
161    dlen = strlen (confd);
162    /* In case there are no configuration files nor directory */
163    FcInit ();
164    if (access (confd, F_OK) == 0)
165    {
166	fprintf (stderr, "%s unexpectedly exists\n", confd);
167	goto bail;
168    }
169    FcFini ();
170    if (!unlink_dirs (tmp))
171    {
172	fprintf (stderr, "Unable to clean up\n");
173	goto bail;
174    }
175    /* In case there are the user configuration file */
176    strcpy (fn, tmp);
177    strcpy (&fn[len], "/.fonts.conf");
178    strcpy (nfn, confd);
179    strcpy (&nfn[dlen], "/fonts.conf");
180    if (!mkdir_p (confd))
181    {
182	fprintf (stderr, "Unable to create a config dir: %s\n", confd);
183	goto bail;
184    }
185    if ((fp = fopen (fn, "wb")) == NULL)
186    {
187	fprintf (stderr, "Unable to create a config file: %s\n", fn);
188	goto bail;
189    }
190    fwrite (content, sizeof (char), strlen (content), fp);
191    fclose (fp);
192    FcInit ();
193    if (access (nfn, F_OK) != 0)
194    {
195	fprintf (stderr, "migration failed for %s\n", nfn);
196	goto bail;
197    }
198    FcFini ();
199    if (!unlink_dirs (tmp))
200    {
201	fprintf (stderr, "Unable to clean up\n");
202	goto bail;
203    }
204    /* In case there are the user configuration dir */
205    strcpy (ud, tmp);
206    strcpy (&ud[len], "/.fonts.conf.d");
207    strcpy (nud, confd);
208    strcpy (&nud[dlen], "/conf.d");
209    if (!mkdir_p (ud))
210    {
211	fprintf (stderr, "Unable to create a config dir: %s\n", ud);
212	goto bail;
213    }
214    FcInit ();
215    if (access (nud, F_OK) != 0)
216    {
217	fprintf (stderr, "migration failed for %s\n", nud);
218	goto bail;
219    }
220    FcFini ();
221
222    ret = 0;
223bail:
224    unlink_dirs (tmp);
225
226    return ret;
227}
228