fccompat.c revision a32e9e42
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#define FC_O_CLOEXEC O_CLOEXEC 50#else 51#define FC_O_CLOEXEC 0 52#endif 53#ifdef O_LARGEFILE 54#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#if !defined (HAVE_MKOSTEMP) && !defined(HAVE_MKSTEMP) && !defined(HAVE__MKTEMP_S) 75static int 76mkstemp (char *template) 77{ 78 static const char s[] = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; 79 int fd, i; 80 size_t l; 81 82 if (template == NULL) 83 { 84 errno = EINVAL; 85 return -1; 86 } 87 l = strlen (template); 88 if (l < 6 || strcmp (&template[l - 6], "XXXXXX") != 0) 89 { 90 errno = EINVAL; 91 return -1; 92 } 93 do 94 { 95 errno = 0; 96 for (i = l - 6; i < l; i++) 97 { 98 int r = FcRandom (); 99 template[i] = s[r % 62]; 100 } 101 fd = FcOpen (template, FC_O_BINARY | O_CREAT | O_EXCL | FC_O_TEMPORARY | FC_O_NOINHERIT | O_RDWR, 0600); 102 } while (fd < 0 && errno == EEXIST); 103 if (fd >= 0) 104 errno = 0; 105 106 return fd; 107} 108#define HAVE_MKSTEMP 1 109#endif 110 111int 112FcOpen(const char *pathname, int flags, ...) 113{ 114 int fd = -1; 115 116 if (flags & O_CREAT) 117 { 118 va_list ap; 119 mode_t mode; 120 121 va_start(ap, flags); 122 mode = (mode_t) va_arg(ap, int); 123 va_end(ap); 124 125 fd = open(pathname, flags | FC_O_CLOEXEC | FC_O_LARGEFILE, mode); 126 } 127 else 128 { 129 fd = open(pathname, flags | FC_O_CLOEXEC | FC_O_LARGEFILE); 130 } 131 132 return fd; 133} 134 135int 136FcMakeTempfile (char *template) 137{ 138 int fd = -1; 139 140#if HAVE_MKOSTEMP 141 fd = mkostemp (template, FC_O_CLOEXEC); 142#elif HAVE_MKSTEMP 143 fd = mkstemp (template); 144# ifdef F_DUPFD_CLOEXEC 145 if (fd != -1) 146 { 147 int newfd = fcntl(fd, F_DUPFD_CLOEXEC, STDIN_FILENO); 148 149 close(fd); 150 fd = newfd; 151 } 152# elif defined(FD_CLOEXEC) 153 if (fd != -1) 154 { 155 fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC); 156 } 157# endif 158#elif HAVE__MKTEMP_S 159 if (_mktemp_s(template, strlen(template) + 1) != 0) 160 return -1; 161 fd = FcOpen(template, O_RDWR | O_EXCL | O_CREAT, 0600); 162#endif 163 164 return fd; 165} 166 167int32_t 168FcRandom(void) 169{ 170 int32_t result; 171 172#if HAVE_RANDOM_R 173 static struct random_data fcrandbuf; 174 static char statebuf[256]; 175 static FcBool initialized = FcFalse; 176#ifdef _AIX 177 static char *retval; 178 long res; 179#endif 180 181 if (initialized != FcTrue) 182 { 183#ifdef _AIX 184 initstate_r (time (NULL), statebuf, 256, &retval, &fcrandbuf); 185#else 186 initstate_r (time (NULL), statebuf, 256, &fcrandbuf); 187#endif 188 initialized = FcTrue; 189 } 190 191#ifdef _AIX 192 random_r (&res, &fcrandbuf); 193 result = (int32_t)res; 194#else 195 random_r (&fcrandbuf, &result); 196#endif 197#elif HAVE_RANDOM 198 static char statebuf[256]; 199 char *state; 200 static FcBool initialized = FcFalse; 201 202 if (initialized != FcTrue) 203 { 204 state = initstate (time (NULL), statebuf, 256); 205 initialized = FcTrue; 206 } 207 else 208 state = setstate (statebuf); 209 210 result = random (); 211 212 setstate (state); 213#elif HAVE_LRAND48 214 result = lrand48 (); 215#elif HAVE_RAND_R 216 static unsigned int seed = time (NULL); 217 218 result = rand_r (&seed); 219#elif HAVE_RAND 220 static FcBool initialized = FcFalse; 221 222 if (initialized != FcTrue) 223 { 224 srand (time (NULL)); 225 initialized = FcTrue; 226 } 227 result = rand (); 228#else 229# error no random number generator function available. 230#endif 231 232 return result; 233} 234 235#ifdef _WIN32 236#include <direct.h> 237#define mkdir(path,mode) _mkdir(path) 238#endif 239 240FcBool 241FcMakeDirectory (const FcChar8 *dir) 242{ 243 FcChar8 *parent; 244 FcBool ret; 245 246 if (strlen ((char *) dir) == 0) 247 return FcFalse; 248 249 parent = FcStrDirname (dir); 250 if (!parent) 251 return FcFalse; 252 if (access ((char *) parent, F_OK) == 0) 253 ret = mkdir ((char *) dir, 0755) == 0 && chmod ((char *) dir, 0755) == 0; 254 else if (access ((char *) parent, F_OK) == -1) 255 ret = FcMakeDirectory (parent) && (mkdir ((char *) dir, 0755) == 0) && chmod ((char *) dir, 0755) == 0; 256 else 257 ret = FcFalse; 258 FcStrFree (parent); 259 return ret; 260} 261 262ssize_t 263FcReadLink (const FcChar8 *pathname, 264 FcChar8 *buf, 265 size_t bufsiz) 266{ 267#ifdef HAVE_READLINK 268 return readlink ((const char *) pathname, (char *)buf, bufsiz); 269#else 270 /* XXX: this function is only used for FcConfigRealFilename() so far 271 * and returning -1 as an error still just works. 272 */ 273 errno = ENOSYS; 274 return -1; 275#endif 276} 277 278#define __fccompat__ 279#include "fcaliastail.h" 280#undef __fccompat__ 281