diff options
Diffstat (limited to 'src/lib/compat.c')
-rw-r--r-- | src/lib/compat.c | 268 |
1 files changed, 268 insertions, 0 deletions
diff --git a/src/lib/compat.c b/src/lib/compat.c new file mode 100644 index 0000000..524ef37 --- /dev/null +++ b/src/lib/compat.c @@ -0,0 +1,268 @@ +/* Copyright (c) 2002-2018 Dovecot authors, see the included COPYING file */ + +#include "config.h" +#undef HAVE_CONFIG_H + +/* Linux needs the _XOPEN_SOURCE define, but others don't. It needs to be + defined before unistd.h, so we need the above config.h include hack.. */ +#ifdef PREAD_WRAPPERS +# define _XOPEN_SOURCE 500 /* Linux */ +#endif + +#define IN_COMPAT_C +#include "lib.h" + +#include <stdio.h> +#include <ctype.h> +#include <unistd.h> +#include <syslog.h> +#include <time.h> +#include <sys/time.h> + +#ifndef INADDR_NONE +# define INADDR_NONE INADDR_BROADCAST +#endif + +#if !defined (HAVE_STRCASECMP) && !defined (HAVE_STRICMP) +int i_my_strcasecmp(const char *s1, const char *s2) +{ + while (*s1 != '\0' && i_toupper(*s1) == i_toupper(*s2)) { + s1++; s2++; + } + + return i_toupper(*s1) - i_toupper(*s2); +} + +int i_my_strncasecmp(const char *s1, const char *s2, size_t max_chars) +{ + while (max_chars > 1 && *s1 != '\0' && + i_toupper(*s1) == i_toupper(*s2)) { + s1++; s2++; max_chars--; + } + + return i_toupper(*s1) - i_toupper(*s2); +} +#endif + +#ifndef HAVE_INET_ATON +int i_my_inet_aton(const char *cp, struct in_addr *inp) +{ + in_addr_t addr; + + addr = inet_addr(cp); + if (addr == INADDR_NONE) + return 0; + + inp->s_addr = addr; + return 1; +} +#endif + +#ifndef HAVE_VSYSLOG +void i_my_vsyslog(int priority, const char *format, va_list args) +{ + T_BEGIN { + syslog(priority, "%s", t_strdup_vprintf(format, args)); + } T_END; +} +#endif + +#ifndef HAVE_GETPAGESIZE +int i_my_getpagesize(void) +{ +#ifdef _SC_PAGESIZE + return sysconf(_SC_PAGESIZE); +#else +# ifdef __GNUC__ +# warning Guessing page size to be 4096 +# endif + return 4096; +#endif +} +#endif + +#ifndef HAVE_WRITEV +ssize_t i_my_writev(int fd, const struct iovec *iov, int iov_len) +{ + size_t written; + ssize_t ret; + int i; + + written = 0; + for (i = 0; i < iov_len; i++, iov++) { + ret = write(fd, iov->iov_base, iov->iov_len); + if (ret < 0) + return -1; + + written += ret; + if ((size_t)ret != iov->iov_len) + break; + } + + if (written > SSIZE_T_MAX) { + errno = ERANGE; + return -1; + } + + return (ssize_t)written; +} +#endif + +#if !defined(HAVE_PREAD) || defined(PREAD_BROKEN) +ssize_t i_my_pread(int fd, void *buf, size_t count, off_t offset) +{ + ssize_t ret; + off_t old_offset; + + old_offset = lseek(fd, 0, SEEK_CUR); + if (old_offset == -1) + return -1; + + if (lseek(fd, offset, SEEK_SET) < 0) + return -1; + + ret = read(fd, buf, count); + if (ret < 0) + return -1; + + if (lseek(fd, old_offset, SEEK_SET) < 0) + return -1; + return ret; +} + +ssize_t i_my_pwrite(int fd, const void *buf, size_t count, off_t offset) +{ + ssize_t ret; + off_t old_offset; + + old_offset = lseek(fd, 0, SEEK_CUR); + if (old_offset == -1) + return -1; + + if (lseek(fd, offset, SEEK_SET) < 0) + return -1; + + ret = write(fd, buf, count); + if (ret < 0) + return -1; + + if (lseek(fd, old_offset, SEEK_SET) < 0) + return -1; + return ret; +} +#elif defined(PREAD_WRAPPERS) + +ssize_t i_my_pread(int fd, void *buf, size_t count, off_t offset) +{ + ssize_t ret; + + ret = pread(fd, buf, count, offset); + return ret; +} + +ssize_t i_my_pwrite(int fd, const void *buf, size_t count, off_t offset) +{ + return pwrite(fd, buf, count, offset); +} +#endif + +#ifndef HAVE_SETEUID +int i_my_seteuid(uid_t euid) +{ +#ifdef HAVE_SETREUID + /* HP-UX at least doesn't have seteuid() but has setreuid() */ + return setreuid(-1, euid); +#else +# error Missing seteuid functionality +#endif +} +#endif + +#ifndef HAVE_SETEGID +int i_my_setegid(gid_t egid) +{ +#ifdef HAVE_SETRESGID + /* HP-UX at least doesn't have setegid() but has setresgid() */ + return setresgid(-1, egid, -1); +#else +# error Missing setegid functionality +#endif +} +#endif + +#ifndef HAVE_LIBGEN_H +char *i_my_basename(char *path) +{ + char *p; + + /* note that this isn't POSIX-compliant basename() replacement. + too much trouble without any gain. */ + p = strrchr(path, '/'); + return p == NULL ? path : p + 1; +} +#endif + +#ifdef HAVE_OLD_VSNPRINTF +#undef vsnprintf +int i_my_vsnprintf(char *str, size_t size, const char *format, va_list ap) +{ + size_t tmp_size; + char *tmp; + int ret; + + /* On overflow HP-UX returns -1, IRIX and Tru64 return size-1. */ + ret = vsnprintf(str, size, format, ap); + if (ret >= 0 && (size_t)ret+1 != size) + return ret; + + /* see if data stack has enough available space for it */ + tmp_size = t_get_bytes_available(); + if (tmp_size > size) { + tmp = t_buffer_get(tmp_size); + ret = vsnprintf(tmp, tmp_size, format, ap); + if (ret >= 0 && (size_t)ret+1 != tmp_size) { + if (size > 0) { + memcpy(str, tmp, size-1); + str[size-1] = '\0'; + } + return ret; + } + } else { + tmp_size = size; + } + + /* try to allocate enough memory to get it to fit. */ + do { + tmp_size = nearest_power(tmp_size+1); + tmp = i_malloc(tmp_size); + ret = vsnprintf(tmp, tmp_size, format, ap); + if (ret >= 0 && (size_t)ret+1 != tmp_size) { + if (size > 0) { + memcpy(str, tmp, size-1); + str[size-1] = '\0'; + } + i_free(tmp); + return ret; + } + i_free(tmp); + } while (tmp_size < 1024*1024); + + i_panic("my_vsnprintf(): Output string too big"); +} +#endif + +#ifndef HAVE_CLOCK_GETTIME +int i_my_clock_gettime(int clk_id, struct timespec *tp) +{ + struct timeval tv; + + i_assert(clk_id == CLOCK_REALTIME); + + /* fallback to using microseconds */ + if (gettimeofday(&tv, NULL) < 0) + return -1; + tp->tv_sec = tv.tv_sec; + tp->tv_nsec = tv.tv_usec * 1000; + return 0; +} +#endif |