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