/* * fontconfig/src/fccompat.c * * Copyright © 2012 Red Hat, Inc. * * Author(s): * Akira TAGOH * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that * the above copyright notice appear in all copies and that both that * copyright notice and this permission notice appear in supporting * documentation, and that the name of the author(s) not be used in * advertising or publicity pertaining to distribution of the software without * specific, written prior permission. The authors make no * representations about the suitability of this software for any purpose. It * is provided "as is" without express or implied warranty. * * THE AUTHOR(S) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO * EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #include "fcint.h" #include #if HAVE_SYS_TYPES_H #include #endif #if HAVE_SYS_STAT_H #include #endif #if HAVE_FCNTL_H #include #endif #if HAVE_UNISTD_H #include #endif #include #include #include #include #ifdef O_CLOEXEC #define FC_O_CLOEXEC O_CLOEXEC #else #define FC_O_CLOEXEC 0 #endif #ifdef O_LARGEFILE #define FC_O_LARGEFILE O_LARGEFILE #else #define FC_O_LARGEFILE 0 #endif #ifdef O_BINARY #define FC_O_BINARY O_BINARY #else #define FC_O_BINARY 0 #endif #ifdef O_TEMPORARY #define FC_O_TEMPORARY O_TEMPORARY #else #define FC_O_TEMPORARY 0 #endif #ifdef O_NOINHERIT #define FC_O_NOINHERIT O_NOINHERIT #else #define FC_O_NOINHERIT 0 #endif #if !defined (HAVE_MKOSTEMP) && !defined(HAVE_MKSTEMP) && !defined(HAVE__MKTEMP_S) static int mkstemp (char *template) { static const char s[] = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; int fd, i; size_t l; if (template == NULL) { errno = EINVAL; return -1; } l = strlen (template); if (l < 6 || strcmp (&template[l - 6], "XXXXXX") != 0) { errno = EINVAL; return -1; } do { errno = 0; for (i = l - 6; i < l; i++) { int r = FcRandom (); template[i] = s[r % 62]; } fd = FcOpen (template, FC_O_BINARY | O_CREAT | O_EXCL | FC_O_TEMPORARY | FC_O_NOINHERIT | O_RDWR, 0600); } while (fd < 0 && errno == EEXIST); if (fd >= 0) errno = 0; return fd; } #define HAVE_MKSTEMP 1 #endif int FcOpen(const char *pathname, int flags, ...) { int fd = -1; if (flags & O_CREAT) { va_list ap; mode_t mode; va_start(ap, flags); mode = (mode_t) va_arg(ap, int); va_end(ap); fd = open(pathname, flags | FC_O_CLOEXEC | FC_O_LARGEFILE, mode); } else { fd = open(pathname, flags | FC_O_CLOEXEC | FC_O_LARGEFILE); } return fd; } int FcMakeTempfile (char *template) { int fd = -1; #if HAVE_MKOSTEMP fd = mkostemp (template, FC_O_CLOEXEC); #elif HAVE_MKSTEMP fd = mkstemp (template); # ifdef F_DUPFD_CLOEXEC if (fd != -1) { int newfd = fcntl(fd, F_DUPFD_CLOEXEC, STDIN_FILENO); close(fd); fd = newfd; } # elif defined(FD_CLOEXEC) if (fd != -1) { fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC); } # endif #elif HAVE__MKTEMP_S if (_mktemp_s(template, strlen(template) + 1) != 0) return -1; fd = FcOpen(template, O_RDWR | O_EXCL | O_CREAT, 0600); #endif return fd; } int32_t FcRandom(void) { int32_t result; #if HAVE_RANDOM_R static struct random_data fcrandbuf; static char statebuf[256]; static FcBool initialized = FcFalse; #ifdef _AIX static char *retval; long res; #endif if (initialized != FcTrue) { #ifdef _AIX initstate_r (time (NULL), statebuf, 256, &retval, &fcrandbuf); #else initstate_r (time (NULL), statebuf, 256, &fcrandbuf); #endif initialized = FcTrue; } #ifdef _AIX random_r (&res, &fcrandbuf); result = (int32_t)res; #else random_r (&fcrandbuf, &result); #endif #elif HAVE_RANDOM static char statebuf[256]; char *state; static FcBool initialized = FcFalse; if (initialized != FcTrue) { state = initstate (time (NULL), statebuf, 256); initialized = FcTrue; } else state = setstate (statebuf); result = random (); setstate (state); #elif HAVE_LRAND48 result = lrand48 (); #elif HAVE_RAND_R static unsigned int seed = time (NULL); result = rand_r (&seed); #elif HAVE_RAND static FcBool initialized = FcFalse; if (initialized != FcTrue) { srand (time (NULL)); initialized = FcTrue; } result = rand (); #else # error no random number generator function available. #endif return result; } #ifdef _WIN32 #include #define mkdir(path,mode) _mkdir(path) #endif FcBool FcMakeDirectory (const FcChar8 *dir) { FcChar8 *parent; FcBool ret; if (strlen ((char *) dir) == 0) return FcFalse; parent = FcStrDirname (dir); if (!parent) return FcFalse; if (access ((char *) parent, F_OK) == 0) ret = mkdir ((char *) dir, 0755) == 0 && chmod ((char *) dir, 0755) == 0; else if (access ((char *) parent, F_OK) == -1) ret = FcMakeDirectory (parent) && (mkdir ((char *) dir, 0755) == 0) && chmod ((char *) dir, 0755) == 0; else ret = FcFalse; FcStrFree (parent); return ret; } ssize_t FcReadLink (const FcChar8 *pathname, FcChar8 *buf, size_t bufsiz) { #ifdef HAVE_READLINK return readlink ((const char *) pathname, (char *)buf, bufsiz); #else /* XXX: this function is only used for FcConfigRealFilename() so far * and returning -1 as an error still just works. */ errno = ENOSYS; return -1; #endif } #define __fccompat__ #include "fcaliastail.h" #undef __fccompat__