1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
|
From c9862b6ea7c3234b29f6500c7d07359847e55ed7 Mon Sep 17 00:00:00 2001
From: Akira TAGOH <akira@tagoh.org>
Date: Mon, 28 Oct 2019 17:11:38 +0900
Subject: [PATCH 1/9] Read latest cache in paths
Right now fontconfig uses a cache found first in a path and
cachedirs are the order of the system-wide path and then the user path.
this is due to avoid writing caches into the user path when running as root.
However, changing caches by certain config only, e.g. using <match target="scan">
may not take effect by this behavior, because it may be stored into the user path.
Thus, needing to find the latest cache out from paths.
Fixes https://gitlab.freedesktop.org/fontconfig/fontconfig/issues/182
---
src/fccache.c | 36 +++++++++++++++++++++-----
test/run-test.sh | 66 ++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 96 insertions(+), 6 deletions(-)
diff --git a/src/fccache.c b/src/fccache.c
index 0976201..4acde22 100644
--- a/src/fccache.c
+++ b/src/fccache.c
@@ -338,7 +338,7 @@ FcDirCacheOpenFile (const FcChar8 *cache_file, struct stat *file_stat)
static FcBool
FcDirCacheProcess (FcConfig *config, const FcChar8 *dir,
FcBool (*callback) (FcConfig *config, int fd, struct stat *fd_stat,
- struct stat *dir_stat, void *closure),
+ struct stat *dir_stat, struct timeval *cache_mtime, void *closure),
void *closure, FcChar8 **cache_file_ret)
{
int fd = -1;
@@ -348,6 +348,7 @@ FcDirCacheProcess (FcConfig *config, const FcChar8 *dir,
struct stat file_stat, dir_stat;
FcBool ret = FcFalse;
const FcChar8 *sysroot = FcConfigGetSysRoot (config);
+ struct timeval latest_mtime = (struct timeval){ 0 };
if (sysroot)
d = FcStrBuildFilename (sysroot, dir, NULL);
@@ -383,15 +384,18 @@ FcDirCacheProcess (FcConfig *config, const FcChar8 *dir,
#endif
fd = FcDirCacheOpenFile (cache_hashed, &file_stat);
if (fd >= 0) {
- ret = (*callback) (config, fd, &file_stat, &dir_stat, closure);
+ ret = (*callback) (config, fd, &file_stat, &dir_stat, &latest_mtime, closure);
close (fd);
if (ret)
{
if (cache_file_ret)
+ {
+ if (*cache_file_ret)
+ FcStrFree (*cache_file_ret);
*cache_file_ret = cache_hashed;
+ }
else
FcStrFree (cache_hashed);
- break;
}
}
#ifndef _WIN32
@@ -414,7 +418,8 @@ FcDirCacheProcess (FcConfig *config, const FcChar8 *dir,
}
}
#endif
- FcStrFree (cache_hashed);
+ else
+ FcStrFree (cache_hashed);
}
FcStrListDone (list);
@@ -998,12 +1003,31 @@ FcDirCacheUnload (FcCache *cache)
}
static FcBool
-FcDirCacheMapHelper (FcConfig *config, int fd, struct stat *fd_stat, struct stat *dir_stat, void *closure)
+FcDirCacheMapHelper (FcConfig *config, int fd, struct stat *fd_stat, struct stat *dir_stat, struct timeval *latest_cache_mtime, void *closure)
{
FcCache *cache = FcDirCacheMapFd (config, fd, fd_stat, dir_stat);
+ struct timeval cache_mtime;
if (!cache)
return FcFalse;
+ cache_mtime.tv_sec = fd_stat->st_mtime;
+#ifdef HAVE_STRUCT_STAT_ST_MTIM
+ cache_mtime.tv_usec = fd_stat->st_mtim.tv_nsec / 1000;
+#else
+ cache_mtime.tv_usec = 0;
+#endif
+ if (timercmp (latest_cache_mtime, &cache_mtime, <))
+ {
+ if (*((FcCache **) closure))
+ FcDirCacheUnload (*((FcCache **) closure));
+ }
+ else
+ {
+ FcDirCacheUnload (cache);
+ return FcFalse;
+ }
+ latest_cache_mtime->tv_sec = cache_mtime.tv_sec;
+ latest_cache_mtime->tv_usec = cache_mtime.tv_usec;
*((FcCache **) closure) = cache;
return FcTrue;
}
@@ -1093,7 +1117,7 @@ FcDirChecksumNano (struct stat *statb)
* the magic number and the size field
*/
static FcBool
-FcDirCacheValidateHelper (FcConfig *config, int fd, struct stat *fd_stat, struct stat *dir_stat, void *closure FC_UNUSED)
+FcDirCacheValidateHelper (FcConfig *config, int fd, struct stat *fd_stat, struct stat *dir_stat, struct timeval *latest_cache_mtime, void *closure FC_UNUSED)
{
FcBool ret = FcTrue;
FcCache c;
diff --git a/test/run-test.sh b/test/run-test.sh
index 4e5968b..8ad09e3 100644
--- a/test/run-test.sh
+++ b/test/run-test.sh
@@ -340,6 +340,72 @@ fi
rm -rf $MyPWD/sysroot
+dotest "read newer caches when multiple places are allowed to store"
+prep
+cp $FONT1 $FONT2 $FONTDIR
+if [ -n ${SOURCE_DATE_EPOCH:-} ] && [ ${#SOURCE_DATE_EPOCH} -gt 0 ]; then
+ touch -m -t "`date -d \"@${SOURCE_DATE_EPOCH}\" +%y%m%d%H%M.%S`" $FONTDIR
+fi
+MYCACHEBASEDIR=`mktemp -d /tmp/fontconfig.XXXXXXXX`
+MYCACHEDIR=$MYCACHEBASEDIR/cache.dir
+MYOWNCACHEDIR=$MYCACHEBASEDIR/owncache.dir
+MYCONFIG=`mktemp /tmp/fontconfig.XXXXXXXX`
+
+mkdir -p $MYCACHEDIR
+mkdir -p $MYOWNCACHEDIR
+
+sed "s!@FONTDIR@!$FONTDIR!
+s!@REMAPDIR@!!
+s!@CACHEDIR@!$MYCACHEDIR!" < $TESTDIR/fonts.conf.in > my-fonts.conf
+
+FONTCONFIG_FILE=$MyPWD/my-fonts.conf $FCCACHE $FONTDIR
+
+sleep 1
+cat<<EOF>$MYCONFIG
+<fontconfig>
+ <match target="scan">
+ <test name="file"><string>$FONTDIR/4x6.pcf</string></test>
+ <edit name="pixelsize"><int>8</int></edit>
+ </match>
+</fontconfig>
+EOF
+sed "s!@FONTDIR@!$FONTDIR!
+s!@REMAPDIR@!<include ignore_missing=\"yes\">$MYCONFIG</include>!
+s!@CACHEDIR@!$MYOWNCACHEDIR!" < $TESTDIR/fonts.conf.in > my-fonts.conf
+
+if [ -n ${SOURCE_DATE_EPOCH:-} ]; then
+ old_epoch=${SOURCE_DATE_EPOCH}
+ SOURCE_DATE_EPOCH=`expr $SOURCE_DATE_EPOCH + 1`
+fi
+FONTCONFIG_FILE=$MyPWD/my-fonts.conf $FCCACHE -f $FONTDIR
+if [ -n ${SOURCE_DATE_EPOCH:-} ]; then
+ SOURCE_DATE_EPOCH=${old_epoch}
+fi
+
+sed "s!@FONTDIR@!$FONTDIR!
+s!@REMAPDIR@!<include ignore_missing=\"yes\">$MYCONFIG</include>!
+s!@CACHEDIR@!$MYCACHEDIR</cachedir><cachedir>$MYOWNCACHEDIR!" < $TESTDIR/fonts.conf.in > my-fonts.conf
+
+FONTCONFIG_FILE=$MyPWD/my-fonts.conf $FCLIST - family pixelsize | sort > my-out
+echo "=" >> my-out
+FONTCONFIG_FILE=$MyPWD/my-fonts.conf $FCLIST - family pixelsize | sort >> my-out
+echo "=" >> my-out
+FONTCONFIG_FILE=$MyPWD/my-fonts.conf $FCLIST - family pixelsize | sort >> my-out
+tr -d '\015' <my-out >my-out.tmp; mv my-out.tmp my-out
+sed -e 's/pixelsize=6/pixelsize=8/g' $BUILDTESTDIR/$EXPECTED > my-out.expected
+
+if cmp my-out my-out.expected > /dev/null ; then : ; else
+ echo "*** Test failed: $TEST"
+ echo "*** output is in 'my-out', expected output in 'my-out.expected'"
+ echo "Actual Result"
+ cat my-out
+ echo "Expected Result"
+ cat my-out.expected
+ exit 1
+fi
+
+rm -rf $MYCACHEBASEDIR $MYCONFIG my-fonts.conf my-out my-out.expected
+
fi # if [ "x$EXEEXT" = "x" ]
rm -rf $FONTDIR $CACHEFILE $CACHEDIR $BASEDIR $FONTCONFIG_FILE out
--
2.24.1
From a45fc8a33256d9d3ea0ea7947f33c8e5e3cc7238 Mon Sep 17 00:00:00 2001
From: Akira TAGOH <akira@tagoh.org>
Date: Thu, 31 Oct 2019 16:15:25 +0900
Subject: [PATCH 2/9] Fix a memory leak caused by the previous commit
---
src/fccache.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/src/fccache.c b/src/fccache.c
index 4acde22..c565560 100644
--- a/src/fccache.c
+++ b/src/fccache.c
@@ -397,6 +397,8 @@ FcDirCacheProcess (FcConfig *config, const FcChar8 *dir,
else
FcStrFree (cache_hashed);
}
+ else
+ FcStrFree (cache_hashed);
}
#ifndef _WIN32
else if (!retried)
@@ -416,6 +418,8 @@ FcDirCacheProcess (FcConfig *config, const FcChar8 *dir,
break;
goto retry;
}
+ else
+ FcStrFree (cache_hashed);
}
#endif
else
--
2.24.1
|