diff options
author | Stef Walter <stefw@redhat.com> | 2016-11-29 13:30:55 +0100 |
---|---|---|
committer | Stef Walter <stefw@redhat.com> | 2016-11-29 13:32:23 +0100 |
commit | 561ee23f218c7a68a2ef46525502f978e56fc1bb (patch) | |
tree | 8deb8569f109a0e9dea11736f56ad5e47f42dc11 /common/compat.c | |
parent | a96f354c3068edb6c8ac80ae6d9a6611651145d7 (diff) | |
download | p11-kit-master.tar.gz |
This repository has moved to GitHub to allow further contributions
and more flexibility who can merge changes.
More details here:
https://lists.freedesktop.org/archives/p11-glue/2016-November/000626.html
Diffstat (limited to 'common/compat.c')
-rw-r--r-- | common/compat.c | 924 |
1 files changed, 0 insertions, 924 deletions
diff --git a/common/compat.c b/common/compat.c deleted file mode 100644 index de5b99b..0000000 --- a/common/compat.c +++ /dev/null @@ -1,924 +0,0 @@ -/* - * Copyright (c) 2011 Collabora Ltd. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above - * copyright notice, this list of conditions and the - * following disclaimer. - * * Redistributions in binary form must reproduce the - * above copyright notice, this list of conditions and - * the following disclaimer in the documentation and/or - * other materials provided with the distribution. - * * The names of contributors to this software may not be - * used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF - * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. - * - * Author: Stef Walter <stefw@collabora.co.uk> - */ - -#include "config.h" - -/* - * This is needed to expose pthread_mutexattr_settype and PTHREAD_MUTEX_DEFAULT - * on older pthreads implementations - */ -#define _XOPEN_SOURCE 700 - -#include "compat.h" - -#include <assert.h> -#include <dirent.h> -#include <errno.h> -#include <stdlib.h> -#include <string.h> - -/*- - * Portions of this file are covered by the following copyright: - * - * Copyright (c) 2001 Mike Barcroft <mike@FreeBSD.org> - * Copyright (c) 1990, 1993 - * Copyright (c) 1987, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Chris Torek. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef HAVE_GETPROGNAME - -#ifdef OS_UNIX - -#include <unistd.h> - -#if defined (HAVE_PROGRAM_INVOCATION_SHORT_NAME) && !HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME -extern char *program_invocation_short_name; -#endif - -#if defined (HAVE___PROGNAME) && !HAVE_DECL___PROGNAME -extern char *__progname; -#endif - -const char * -getprogname (void) -{ - const char *name; - -#if defined (HAVE_GETEXECNAME) - const char *p; - name = getexecname(); - p = strrchr (name ? name : "", '/'); - if (p != NULL) - name = p + 1; -#elif defined (HAVE_PROGRAM_INVOCATION_SHORT_NAME) - name = program_invocation_short_name; -#elif defined (HAVE___PROGNAME) - name = __progname; -#else - #error No way to retrieve short program name -#endif - - return name; -} - -#else /* OS_WIN32 */ - -extern char **__argv; -static char prognamebuf[256]; - -const char * -getprogname (void) -{ - const char *name; - const char *p, *p2; - size_t length; - - name = __argv[0]; - if (name == NULL) - return NULL; - - p = strrchr (name, '\\'); - p2 = strrchr (name, '/'); - if (p2 > p) - p = p2; - if (p != NULL) - name = p + 1; - - length = sizeof (prognamebuf) - 1; - strncpy (prognamebuf, name, length); - prognamebuf[length] = 0; - length = strlen (prognamebuf); - if (length > 4 && _stricmp (prognamebuf + (length - 4), ".exe") == 0) - prognamebuf[length - 4] = '\0'; - - return prognamebuf; -} - -#endif /* OS_WIN32 */ - -#endif /* HAVE_GETPROGNAME */ - -#ifdef OS_UNIX -#include <sys/stat.h> -#include <sys/mman.h> -#include <fcntl.h> -#include <unistd.h> - -void -p11_mutex_init (p11_mutex_t *mutex) -{ - pthread_mutexattr_t attr; - int ret; - - pthread_mutexattr_init (&attr); - pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_DEFAULT); - ret = pthread_mutex_init (mutex, &attr); - assert (ret == 0); - pthread_mutexattr_destroy (&attr); -} - -char * -p11_dl_error (void) -{ - const char *msg = dlerror (); - return msg ? strdup (msg) : NULL; -} - -struct _p11_mmap { - int fd; - void *data; - size_t size; -}; - -p11_mmap * -p11_mmap_open (const char *path, - struct stat *sb, - void **data, - size_t *size) -{ - struct stat stb; - p11_mmap *map; - - map = calloc (1, sizeof (p11_mmap)); - if (map == NULL) - return NULL; - - map->fd = open (path, O_RDONLY | O_CLOEXEC); - if (map->fd == -1) { - free (map); - return NULL; - } - - if (sb == NULL) { - sb = &stb; - if (fstat (map->fd, &stb) < 0) { - close (map->fd); - free (map); - return NULL; - } - } - - /* Workaround for broken ZFS on Linux */ - if (S_ISDIR (sb->st_mode)) { - errno = EISDIR; - close (map->fd); - free (map); - return NULL; - } - - if (sb->st_size == 0) { - *data = ""; - *size = 0; - return map; - } - - map->size = sb->st_size; - map->data = mmap (NULL, map->size, PROT_READ, MAP_PRIVATE, map->fd, 0); - if (map->data == MAP_FAILED) { - close (map->fd); - free (map); - return NULL; - } - - *data = map->data; - *size = map->size; - return map; -} - -void -p11_mmap_close (p11_mmap *map) -{ - if (map->size) - munmap (map->data, map->size); - close (map->fd); - free (map); -} - -#endif /* OS_UNIX */ - -#ifdef OS_WIN32 - -char * -p11_dl_error (void) -{ - DWORD code = GetLastError(); - LPVOID msg_buf; - - FormatMessageA (FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, code, - MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPSTR)&msg_buf, 0, NULL); - - return msg_buf; -} - -void -p11_dl_close (void *dl) -{ - FreeLibrary (dl); -} - -int -p11_thread_create (p11_thread_t *thread, - p11_thread_routine routine, - void *arg) -{ - assert (thread); - - *thread = CreateThread (NULL, 0, - (LPTHREAD_START_ROUTINE)routine, - arg, 0, NULL); - - if (*thread == NULL) - return GetLastError (); - - return 0; -} - -int -p11_thread_join (p11_thread_t thread) -{ - DWORD res; - - res = WaitForSingleObject (thread, INFINITE); - if (res == WAIT_FAILED) - return GetLastError (); - - CloseHandle (thread); - return 0; -} - -struct _p11_mmap { - HANDLE file; - HANDLE mapping; - void *data; -}; - -p11_mmap * -p11_mmap_open (const char *path, - struct stat *sb, - void **data, - size_t *size) -{ - HANDLE mapping; - LARGE_INTEGER large; - DWORD errn; - p11_mmap *map; - - map = calloc (1, sizeof (p11_mmap)); - if (map == NULL) { - errno = ENOMEM; - return NULL; - } - - map->file = CreateFile (path, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS, NULL); - if (map->file == INVALID_HANDLE_VALUE) { - errn = GetLastError (); - free (map); - SetLastError (errn); - if (errn == ERROR_PATH_NOT_FOUND || errn == ERROR_FILE_NOT_FOUND) - errno = ENOENT; - else if (errn == ERROR_ACCESS_DENIED) - errno = EPERM; - return NULL; - } - - if (sb == NULL) { - if (!GetFileSizeEx (map->file, &large)) { - errn = GetLastError (); - CloseHandle (map->file); - free (map); - SetLastError (errn); - if (errn == ERROR_ACCESS_DENIED) - errno = EPERM; - return NULL; - } - } else { - large.QuadPart = sb->st_size; - } - - mapping = CreateFileMapping (map->file, NULL, PAGE_READONLY, 0, 0, NULL); - if (!mapping) { - errn = GetLastError (); - CloseHandle (map->file); - free (map); - SetLastError (errn); - if (errn == ERROR_ACCESS_DENIED) - errno = EPERM; - return NULL; - } - - map->data = MapViewOfFile (mapping, FILE_MAP_READ, 0, 0, large.QuadPart); - CloseHandle (mapping); - - if (map->data == NULL) { - errn = GetLastError (); - CloseHandle (map->file); - free (map); - SetLastError (errn); - if (errn == ERROR_ACCESS_DENIED) - errno = EPERM; - return NULL; - } - - *data = map->data; - *size = large.QuadPart; - return map; -} - -void -p11_mmap_close (p11_mmap *map) -{ - UnmapViewOfFile (map->data); - CloseHandle (map->file); - free (map); -} - -#endif /* OS_WIN32 */ - -#ifndef HAVE_STRNSTR -#include <string.h> - -/* - * Find the first occurrence of find in s, where the search is limited to the - * first slen characters of s. - */ -char * -strnstr (const char *s, - const char *find, - size_t slen) -{ - char c, sc; - size_t len; - - if ((c = *find++) != '\0') { - len = strlen (find); - do { - do { - if (slen-- < 1 || (sc = *s++) == '\0') - return (NULL); - } while (sc != c); - if (len > slen) - return (NULL); - } while (strncmp(s, find, len) != 0); - s--; - } - return ((char *)s); -} - -#endif /* HAVE_STRNSTR */ - -#ifndef HAVE_MEMDUP - -void * -memdup (const void *data, - size_t length) -{ - void *dup; - - if (!data) - return NULL; - - dup = malloc (length); - if (dup != NULL) - memcpy (dup, data, length); - - return dup; -} - -#endif /* HAVE_MEMDUP */ - -/* - * WORKAROUND: So in lots of released builds of firefox a completely broken strndup() - * is present. It does not NULL terminate its string output. It is unconditionally - * defined, and overrides the libc strndup() function on platforms where it - * exists as a function. For this reason we (for now) unconditionally define - * strndup(). - */ - -#if 1 /* #ifndef HAVE_STRNDUP */ - -/* - * HAVE_STRNDUP may be undefined if strndup() isn't working. So it may be - * present, and yet strndup may still be a defined header macro. - */ -#ifdef strndup -#undef strndup -#endif - -char * -strndup (const char *data, - size_t length); - -char * -strndup (const char *data, - size_t length) -{ - char *ret; - - ret = malloc (length + 1); - if (ret != NULL) { - strncpy (ret, data, length); - ret[length] = 0; - } - - return ret; -} - -#endif /* HAVE_STRNDUP */ - -#ifndef HAVE_STRCONCAT - -#include <stdarg.h> - -char * -strconcat (const char *first, - ...) -{ - size_t length = 0; - const char *arg; - char *result, *at; - va_list va; - - va_start (va, first); - - for (arg = first; arg; arg = va_arg (va, const char*)) - length += strlen (arg); - - va_end (va); - - at = result = malloc (length + 1); - if (result == NULL) - return NULL; - - va_start (va, first); - - for (arg = first; arg; arg = va_arg (va, const char*)) { - length = strlen (arg); - memcpy (at, arg, length); - at += length; - } - - va_end (va); - - *at = 0; - return result; -} - -#endif /* HAVE_STRCONCAT */ - -#ifndef HAVE_VASPRINTF -#include <stdio.h> - -int vasprintf(char **strp, const char *fmt, va_list ap); - -int -vasprintf (char **strp, - const char *fmt, - va_list ap) -{ - char *buf = NULL; - char *nbuf; - int guess = 128; - int length = 0; - int ret; - - if (fmt == NULL) { - errno = EINVAL; - return -1; - } - - for (;;) { - nbuf = realloc (buf, guess); - if (!nbuf) { - free (buf); - return -1; - } - - buf = nbuf; - length = guess; - - ret = vsnprintf (buf, length, fmt, ap); - - if (ret < 0) - guess *= 2; - - else if (ret >= length) - guess = ret + 1; - - else - break; - } - - *strp = buf; - return ret; -} - -#endif /* HAVE_VASPRINTF */ - -#ifndef HAVE_ASPRINTF - -int asprintf(char **strp, const char *fmt, ...); - -int -asprintf (char **strp, - const char *fmt, - ...) -{ - va_list va; - int ret; - - va_start (va, fmt); - ret = vasprintf (strp, fmt, va); - va_end (va); - - return ret; -} - -#endif /* HAVE_ASPRINTF */ - -#ifndef HAVE_GMTIME_R - -struct tm * -gmtime_r (const time_t *timep, - struct tm *result) -{ -#ifdef OS_WIN32 - /* - * On win32 gmtime() returns thread local storage, so we can - * just copy it out into the buffer without worrying about races. - */ - struct tm *tg; - tg = gmtime (timep); - if (!tg) - return NULL; - memcpy (result, tg, sizeof (struct tm)); - return result; -#else - #error Need either gmtime_r() function on Unix -#endif -} - -#endif /* HAVE_GMTIME_R */ - -#if !defined(HAVE_MKDTEMP) || !defined(HAVE_MKSTEMP) -#include <sys/stat.h> -#include <fcntl.h> - -static int -_gettemp (char *path, - int *doopen, - int domkdir, - int slen) -{ - static const char padchar[] = - "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; - static const int maxpathlen = 1024; - - char *start, *trv, *suffp, *carryp; - char *pad; - struct stat sbuf; - int rval; - int rnd; - char carrybuf[maxpathlen]; - - if ((doopen != NULL && domkdir) || slen < 0) { - errno = EINVAL; - return (0); - } - - for (trv = path; *trv != '\0'; ++trv) - ; - if (trv - path >= maxpathlen) { - errno = ENAMETOOLONG; - return (0); - } - trv -= slen; - suffp = trv; - --trv; - if (trv < path || NULL != strchr (suffp, '/')) { - errno = EINVAL; - return (0); - } - - /* Fill space with random characters */ - while (trv >= path && *trv == 'X') { - rnd = rand () % sizeof (padchar) - 1; - *trv-- = padchar[rnd]; - } - start = trv + 1; - - /* save first combination of random characters */ - memcpy (carrybuf, start, suffp - start); - - /* - * check the target directory. - */ - if (doopen != NULL || domkdir) { - for (; trv > path; --trv) { - if (*trv == '/') { - *trv = '\0'; - rval = stat(path, &sbuf); - *trv = '/'; - if (rval != 0) - return (0); - if (!S_ISDIR(sbuf.st_mode)) { - errno = ENOTDIR; - return (0); - } - break; - } - } - } - - for (;;) { - if (doopen) { - if ((*doopen = open (path, O_BINARY | O_CREAT | O_EXCL | O_RDWR | O_CLOEXEC, 0600)) >= 0) - return (1); - if (errno != EEXIST) - return (0); - } else if (domkdir) { -#ifdef OS_UNIX - if (mkdir (path, 0700) == 0) -#else - if (mkdir (path) == 0) -#endif - return (1); - if (errno != EEXIST) - return (0); -#ifdef OS_UNIX - } else if (lstat (path, &sbuf)) -#else - } else if (stat (path, &sbuf)) -#endif - return (errno == ENOENT); - - /* If we have a collision, cycle through the space of filenames */ - for (trv = start, carryp = carrybuf;;) { - /* have we tried all possible permutations? */ - if (trv == suffp) - return (0); /* yes - exit with EEXIST */ - pad = strchr(padchar, *trv); - if (pad == NULL) { - /* this should never happen */ - errno = EIO; - return (0); - } - /* increment character */ - *trv = (*++pad == '\0') ? padchar[0] : *pad; - /* carry to next position? */ - if (*trv == *carryp) { - /* increment position and loop */ - ++trv; - ++carryp; - } else { - /* try with new name */ - break; - } - } - } - - /*NOTREACHED*/ -} - -#endif /* !HAVE_MKDTEMP || !HAVE_MKSTEMP */ - -#ifndef HAVE_MKSTEMP - -int -mkstemp (char *template) -{ - int fd; - - return (_gettemp (template, &fd, 0, 0) ? fd : -1); -} - -#endif /* HAVE_MKSTEMP */ - -#ifndef HAVE_MKDTEMP - -char * -mkdtemp (char *template) -{ - return (_gettemp (template, (int *)NULL, 1, 0) ? template : (char *)NULL); -} - -#endif /* HAVE_MKDTEMP */ - -#ifndef HAVE_GETAUXVAL - -unsigned long -getauxval (unsigned long type) -{ - static unsigned long secure = 0UL; - static bool check_secure_initialized = false; - - /* - * This is the only one our stand-in impl supports and is - * also the only type we define in compat.h header - */ - assert (type == AT_SECURE); - - if (!check_secure_initialized) { -#if defined(HAVE___LIBC_ENABLE_SECURE) - extern int __libc_enable_secure; - secure = __libc_enable_secure; - -#elif defined(HAVE_ISSETUGID) - secure = issetugid (); - -#elif defined(OS_UNIX) - uid_t ruid, euid, suid; /* Real, effective and saved user ID's */ - gid_t rgid, egid, sgid; /* Real, effective and saved group ID's */ - -#ifdef HAVE_GETRESUID - if (getresuid (&ruid, &euid, &suid) != 0 || - getresgid (&rgid, &egid, &sgid) != 0) -#endif /* HAVE_GETRESUID */ - { - suid = ruid = getuid (); - sgid = rgid = getgid (); - euid = geteuid (); - egid = getegid (); - } - - secure = (ruid != euid || ruid != suid || - rgid != egid || rgid != sgid); -#endif /* OS_UNIX */ - check_secure_initialized = true; - } - - return secure; -} - -#endif /* HAVE_GETAUXVAL */ - -char * -secure_getenv (const char *name) -{ - if (getauxval (AT_SECURE)) - return NULL; - return getenv (name); -} - -#ifndef HAVE_STRERROR_R - -int -strerror_r (int errnum, - char *buf, - size_t buflen) -{ -#ifdef OS_WIN32 -#if _WIN32_WINNT < 0x502 /* WinXP or older */ - int n = sys_nerr; - const char *p; - if (errnum < 0 || errnum >= n) - p = sys_errlist[n]; - else - p = sys_errlist[errnum]; - if (buf == NULL || buflen == 0) - return EINVAL; - strncpy(buf, p, buflen); - buf[buflen-1] = 0; - return 0; -#else /* Server 2003 or newer */ - return strerror_s (buf, buflen, errnum); -#endif /*_WIN32_WINNT*/ - -#else - #error no strerror_r implementation -#endif -} - -#endif /* HAVE_STRERROR_R */ - -#ifdef OS_UNIX - -#include <unistd.h> - -#ifndef HAVE_FDWALK - -#ifdef HAVE_SYS_RESOURCE_H -#include <sys/resource.h> -#endif - -int -fdwalk (int (* cb) (void *data, int fd), - void *data) -{ - struct dirent *de; - char *end; - DIR *dir; - int open_max; - long num; - int res = 0; - int fd; - -#ifdef HAVE_SYS_RESOURCE_H - struct rlimit rl; -#endif - - dir = opendir ("/proc/self/fd"); - if (dir != NULL) { - while ((de = readdir (dir)) != NULL) { - end = NULL; - num = (int) strtol (de->d_name, &end, 10); - - /* didn't parse or is the opendir() fd */ - if (!end || *end != '\0' || - (int)num == dirfd (dir)) - continue; - - fd = num; - - /* call the callback */ - res = cb (data, fd); - if (res != 0) - break; - } - - closedir (dir); - return res; - } - - /* No /proc, brute force */ -#ifdef HAVE_SYS_RESOURCE_H - if (getrlimit (RLIMIT_NOFILE, &rl) == 0 && rl.rlim_max != RLIM_INFINITY) - open_max = rl.rlim_max; - else -#endif - open_max = sysconf (_SC_OPEN_MAX); - - for (fd = 0; fd < open_max; fd++) { - res = cb (data, fd); - if (res != 0) - break; - } - - return res; -} - -#endif /* HAVE_FDWALK */ - -#endif /* OS_UNIX */ |