Coverage Report

Created: 2025-07-07 10:01

/work/workdir/UnpackedTarball/fontconfig/src/fccompat.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * fontconfig/src/fccompat.c
3
 *
4
 * Copyright © 2012 Red Hat, Inc.
5
 *
6
 * Author(s):
7
 *  Akira TAGOH
8
 *
9
 * Permission to use, copy, modify, distribute, and sell this software and its
10
 * documentation for any purpose is hereby granted without fee, provided that
11
 * the above copyright notice appear in all copies and that both that
12
 * copyright notice and this permission notice appear in supporting
13
 * documentation, and that the name of the author(s) not be used in
14
 * advertising or publicity pertaining to distribution of the software without
15
 * specific, written prior permission.  The authors make no
16
 * representations about the suitability of this software for any purpose.  It
17
 * is provided "as is" without express or implied warranty.
18
 *
19
 * THE AUTHOR(S) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
20
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
21
 * EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY SPECIAL, INDIRECT OR
22
 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
23
 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
24
 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
25
 * PERFORMANCE OF THIS SOFTWARE.
26
 */
27
28
#include "fcint.h"
29
30
#include <errno.h>
31
#if HAVE_SYS_TYPES_H
32
#  include <sys/types.h>
33
#endif
34
#if HAVE_SYS_STAT_H
35
#  include <sys/stat.h>
36
#endif
37
#if HAVE_FCNTL_H
38
#  include <fcntl.h>
39
#endif
40
#if HAVE_UNISTD_H
41
#  include <unistd.h>
42
#endif
43
#include <stdarg.h>
44
#include <stdlib.h>
45
#include <string.h>
46
#include <time.h>
47
48
#ifdef O_CLOEXEC
49
338
#  define FC_O_CLOEXEC O_CLOEXEC
50
#else
51
#  define FC_O_CLOEXEC 0
52
#endif
53
#ifdef O_LARGEFILE
54
336
#  define FC_O_LARGEFILE O_LARGEFILE
55
#else
56
#  define FC_O_LARGEFILE 0
57
#endif
58
#ifdef O_BINARY
59
#  define FC_O_BINARY O_BINARY
60
#else
61
#  define FC_O_BINARY 0
62
#endif
63
#ifdef O_TEMPORARY
64
#  define FC_O_TEMPORARY O_TEMPORARY
65
#else
66
#  define FC_O_TEMPORARY 0
67
#endif
68
#ifdef O_NOINHERIT
69
#  define FC_O_NOINHERIT O_NOINHERIT
70
#else
71
#  define FC_O_NOINHERIT 0
72
#endif
73
74
#ifndef HAVE_UNISTD_H
75
/* Values for the second argument to access. These may be OR'd together. */
76
#  ifndef R_OK
77
#    define R_OK 4 /* Test for read permission.  */
78
#  endif
79
#  ifndef W_OK
80
#    define W_OK 2 /* Test for write permission.  */
81
#  endif
82
#  ifndef F_OK
83
#    define F_OK 0 /* Test for existence.  */
84
#  endif
85
86
typedef int mode_t;
87
#endif /* !HAVE_UNISTD_H */
88
89
#if !defined(HAVE_MKOSTEMP) && !defined(HAVE_MKSTEMP) && !defined(HAVE__MKTEMP_S)
90
static int
91
mkstemp (char *template)
92
{
93
    static const char s[] = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
94
    int               fd, i;
95
    size_t            l;
96
97
    if (template == NULL) {
98
  errno = EINVAL;
99
  return -1;
100
    }
101
    l = strlen (template);
102
    if (l < 6 || strcmp (&template[l - 6], "XXXXXX") != 0) {
103
  errno = EINVAL;
104
  return -1;
105
    }
106
    do {
107
  errno = 0;
108
  for (i = l - 6; i < l; i++) {
109
      int r = FcRandom();
110
      template[i] = s[r % 62];
111
  }
112
  fd = FcOpen (template, FC_O_BINARY | O_CREAT | O_EXCL | FC_O_TEMPORARY | FC_O_NOINHERIT | O_RDWR, 0600);
113
    } while (fd < 0 && errno == EEXIST);
114
    if (fd >= 0)
115
  errno = 0;
116
117
    return fd;
118
}
119
#  define HAVE_MKSTEMP 1
120
#endif
121
122
int
123
FcOpen (const char *pathname, int flags, ...)
124
336
{
125
336
    int fd = -1;
126
127
336
    if (flags & O_CREAT) {
128
2
  va_list ap;
129
2
  mode_t  mode;
130
131
2
  va_start (ap, flags);
132
2
  mode = (mode_t)va_arg (ap, int);
133
2
  va_end (ap);
134
135
2
  fd = open (pathname, flags | FC_O_CLOEXEC | FC_O_LARGEFILE, mode);
136
334
    } else {
137
334
  fd = open (pathname, flags | FC_O_CLOEXEC | FC_O_LARGEFILE);
138
334
    }
139
140
336
    return fd;
141
336
}
142
143
int
144
FcMakeTempfile (char *template)
145
2
{
146
2
    int fd = -1;
147
148
2
#if HAVE_MKOSTEMP
149
2
    fd = mkostemp (template, FC_O_CLOEXEC);
150
#elif HAVE_MKSTEMP
151
    fd = mkstemp (template);
152
#  ifdef F_DUPFD_CLOEXEC
153
    if (fd != -1) {
154
  int newfd = fcntl (fd, F_DUPFD_CLOEXEC, STDIN_FILENO);
155
156
  close (fd);
157
  fd = newfd;
158
    }
159
#  elif defined(FD_CLOEXEC)
160
    if (fd != -1) {
161
  fcntl (fd, F_SETFD, fcntl (fd, F_GETFD) | FD_CLOEXEC);
162
    }
163
#  endif
164
#elif HAVE__MKTEMP_S
165
    if (_mktemp_s (template, strlen (template) + 1) != 0)
166
  return -1;
167
    fd = FcOpen (template, O_RDWR | O_EXCL | O_CREAT, 0600);
168
#endif
169
170
2
    return fd;
171
2
}
172
173
int32_t
174
FcRandom (void)
175
320
{
176
320
    int32_t result;
177
178
320
#if HAVE_RANDOM_R
179
320
    static struct random_data fcrandbuf;
180
320
    static char               statebuf[256];
181
320
    static FcBool             initialized = FcFalse;
182
#  ifdef _AIX
183
    static char *retval;
184
    long         res;
185
#  endif
186
187
320
    if (initialized != FcTrue) {
188
#  ifdef _AIX
189
  initstate_r (time (NULL), statebuf, 256, &retval, &fcrandbuf);
190
#  else
191
106
  initstate_r (time (NULL), statebuf, 256, &fcrandbuf);
192
106
#  endif
193
106
  initialized = FcTrue;
194
106
    }
195
196
#  ifdef _AIX
197
    random_r (&res, &fcrandbuf);
198
    result = (int32_t)res;
199
#  else
200
320
    random_r (&fcrandbuf, &result);
201
320
#  endif
202
#elif HAVE_RANDOM
203
    static char   statebuf[256];
204
    char         *state;
205
    static FcBool initialized = FcFalse;
206
207
    if (initialized != FcTrue) {
208
  state = initstate (time (NULL), statebuf, 256);
209
  initialized = FcTrue;
210
    } else
211
  state = setstate (statebuf);
212
213
    result = random();
214
215
    setstate (state);
216
#elif HAVE_LRAND48
217
    result = lrand48();
218
#elif HAVE_RAND_R
219
    static unsigned int seed;
220
221
    seed = time (NULL);
222
    result = rand_r (&seed);
223
#elif HAVE_RAND
224
    static FcBool initialized = FcFalse;
225
226
    if (initialized != FcTrue) {
227
  srand (time (NULL));
228
  initialized = FcTrue;
229
    }
230
    result = rand();
231
#else
232
#  error no random number generator function available.
233
#endif
234
235
320
    return result;
236
320
}
237
238
#ifdef _WIN32
239
#  include <direct.h>
240
#  define mkdir(path, mode) _mkdir (path)
241
#endif
242
243
FcBool
244
FcMakeDirectory (const FcChar8 *dir)
245
2
{
246
2
    FcChar8 *parent;
247
2
    FcBool   ret;
248
249
2
    if (strlen ((char *)dir) == 0)
250
0
  return FcFalse;
251
252
2
    parent = FcStrDirname (dir);
253
2
    if (!parent)
254
0
  return FcFalse;
255
2
    if (access ((char *)parent, F_OK) == 0)
256
1
  ret = mkdir ((char *)dir, 0755) == 0 && chmod ((char *)dir, 0755) == 0;
257
1
    else if (access ((char *)parent, F_OK) == -1)
258
1
  ret = FcMakeDirectory (parent) && (mkdir ((char *)dir, 0755) == 0) && chmod ((char *)dir, 0755) == 0;
259
0
    else
260
0
  ret = FcFalse;
261
2
    FcStrFree (parent);
262
2
    return ret;
263
2
}
264
265
ssize_t
266
FcReadLink (const FcChar8 *pathname,
267
            FcChar8       *buf,
268
            size_t         bufsiz)
269
106
{
270
106
#ifdef HAVE_READLINK
271
106
    return readlink ((const char *)pathname, (char *)buf, bufsiz);
272
#else
273
    /* XXX: this function is only used for FcConfigRealFilename() so far
274
     * and returning -1 as an error still just works.
275
     */
276
    errno = ENOSYS;
277
    return -1;
278
#endif
279
106
}
280
281
/* On Windows MingW provides dirent.h / openddir(), but MSVC does not */
282
#ifndef HAVE_DIRENT_H
283
284
struct DIR {
285
    struct dirent   d_ent;
286
    HANDLE          handle;
287
    WIN32_FIND_DATA fdata;
288
    FcBool          valid;
289
};
290
291
FcPrivate DIR *
292
FcCompatOpendirWin32 (const char *dirname)
293
{
294
    size_t len;
295
    char  *name;
296
    DIR   *dir;
297
298
    dir = calloc (1, sizeof (struct DIR));
299
    if (dir == NULL)
300
  return NULL;
301
302
    len = strlen (dirname);
303
    name = malloc (len + 3);
304
    if (name == NULL) {
305
  free (dir);
306
  return NULL;
307
    }
308
    memcpy (name, dirname, len);
309
    name[len++] = FC_DIR_SEPARATOR;
310
    name[len++] = '*';
311
    name[len] = '\0';
312
313
    dir->handle = FindFirstFileEx (name, FindExInfoBasic, &dir->fdata, FindExSearchNameMatch, NULL, 0);
314
315
    free (name);
316
317
    if (!dir->handle) {
318
  free (dir);
319
  dir = NULL;
320
321
  if (GetLastError() == ERROR_FILE_NOT_FOUND)
322
      errno = ENOENT;
323
  else
324
      errno = EACCES;
325
    }
326
327
    dir->valid = FcTrue;
328
    return dir;
329
}
330
331
FcPrivate struct dirent *
332
FcCompatReaddirWin32 (DIR *dir)
333
{
334
    if (dir->valid != FcTrue)
335
  return NULL;
336
337
    dir->d_ent.d_name = dir->fdata.cFileName;
338
339
    if ((dir->fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0)
340
  dir->d_ent.d_type = DT_DIR;
341
    else if (dir->fdata.dwFileAttributes == FILE_ATTRIBUTE_NORMAL)
342
  dir->d_ent.d_type = DT_REG;
343
    else
344
  dir->d_ent.d_type = DT_UNKNOWN;
345
346
    if (!FindNextFile (dir->handle, &dir->fdata))
347
  dir->valid = FcFalse;
348
349
    return &dir->d_ent;
350
}
351
352
FcPrivate int
353
FcCompatClosedirWin32 (DIR *dir)
354
{
355
    if (dir != NULL && dir->handle != NULL) {
356
  FindClose (dir->handle);
357
  free (dir);
358
    }
359
    return 0;
360
}
361
#endif /* HAVE_DIRENT_H */
362
363
#define __fccompat__
364
#include "fcaliastail.h"
365
#undef __fccompat__