| /* |
| * 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 <errno.h> |
| #if HAVE_SYS_TYPES_H |
| #include <sys/types.h> |
| #endif |
| #if HAVE_SYS_STAT_H |
| #include <sys/stat.h> |
| #endif |
| #if HAVE_FCNTL_H |
| #include <fcntl.h> |
| #endif |
| #if HAVE_UNISTD_H |
| #include <unistd.h> |
| #endif |
| #include <stdarg.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <time.h> |
| |
| #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 <direct.h> |
| #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__ |