Blame src/compat/compat.h

Packit c32a2d
/*
Packit c32a2d
	compat: Some compatibility functions and header inclusions.
Packit c32a2d
	Basic standard C stuff, that may barely be above/around C89.
Packit c32a2d
Packit c32a2d
	The mpg123 code is determined to keep it's legacy. A legacy of old, old UNIX.
Packit c32a2d
	It is envisioned to include this compat header instead of any of the "standard" headers, to catch compatibility issues.
Packit c32a2d
	So, don't include stdlib.h or string.h ... include compat.h.
Packit c32a2d
Packit c32a2d
	copyright 2007-8 by the mpg123 project - free software under the terms of the LGPL 2.1
Packit c32a2d
	see COPYING and AUTHORS files in distribution or http://mpg123.org
Packit c32a2d
	initially written by Thomas Orgis
Packit c32a2d
*/
Packit c32a2d
Packit c32a2d
#ifndef MPG123_COMPAT_H
Packit c32a2d
#define MPG123_COMPAT_H
Packit c32a2d
Packit c32a2d
#include "config.h"
Packit c32a2d
#include "intsym.h"
Packit c32a2d
Packit c32a2d
/* For --nagging compilation with -std=c89, we need
Packit c32a2d
   to disable the inline keyword. */
Packit c32a2d
#ifdef PLAIN_C89
Packit c32a2d
#ifndef inline
Packit c32a2d
#define inline
Packit c32a2d
#endif
Packit c32a2d
#endif
Packit c32a2d
Packit c32a2d
#include <errno.h>
Packit c32a2d
Packit c32a2d
#ifdef HAVE_STDLIB_H
Packit c32a2d
/* realloc, size_t */
Packit c32a2d
#include <stdlib.h>
Packit c32a2d
#endif
Packit c32a2d
Packit c32a2d
#include        <stdio.h>
Packit c32a2d
#include        <math.h>
Packit c32a2d
Packit c32a2d
#ifdef HAVE_SIGNAL_H
Packit c32a2d
#include <signal.h>
Packit c32a2d
#else
Packit c32a2d
#ifdef HAVE_SYS_SIGNAL_H
Packit c32a2d
#include <sys/signal.h>
Packit c32a2d
#endif
Packit c32a2d
#endif
Packit c32a2d
Packit c32a2d
#ifdef HAVE_UNISTD_H
Packit c32a2d
#include <unistd.h>
Packit c32a2d
#endif
Packit c32a2d
Packit c32a2d
/* Types, types, types. */
Packit c32a2d
/* Do we actually need these two in addition to sys/types.h? As replacement? */
Packit c32a2d
#ifdef HAVE_SYS_TYPES_H
Packit c32a2d
#include <sys/types.h>
Packit c32a2d
#endif
Packit c32a2d
#ifdef HAVE_INTTYPES_H
Packit c32a2d
#include <inttypes.h>
Packit c32a2d
#endif
Packit c32a2d
#ifdef HAVE_STDINT_H
Packit c32a2d
#include <stdint.h>
Packit c32a2d
#endif
Packit c32a2d
/* We want SIZE_MAX, etc. */
Packit c32a2d
#ifdef HAVE_LIMITS_H
Packit c32a2d
#include <limits.h>
Packit c32a2d
#endif
Packit c32a2d
 
Packit c32a2d
#ifndef SIZE_MAX
Packit c32a2d
#define SIZE_MAX ((size_t)-1)
Packit c32a2d
#endif
Packit c32a2d
#ifndef ULONG_MAX
Packit c32a2d
#define ULONG_MAX ((unsigned long)-1)
Packit c32a2d
#endif
Packit c32a2d
Packit c32a2d
#ifdef HAVE_STRING_H
Packit c32a2d
#include <string.h>
Packit c32a2d
#endif
Packit c32a2d
#ifdef HAVE_STRINGS_H
Packit c32a2d
#include <strings.h>
Packit c32a2d
#endif
Packit c32a2d
Packit c32a2d
#ifdef OS2
Packit c32a2d
#include <float.h>
Packit c32a2d
#endif
Packit c32a2d
Packit c32a2d
#ifdef HAVE_SYS_TIME_H
Packit c32a2d
#include <sys/time.h>
Packit c32a2d
#endif
Packit c32a2d
/* For select(), I need select.h according to POSIX 2001, else: sys/time.h sys/types.h unistd.h */
Packit c32a2d
#ifdef HAVE_SYS_SELECT_H
Packit c32a2d
#include <sys/select.h>
Packit c32a2d
#endif
Packit c32a2d
Packit c32a2d
/* compat_open makes little sense without */
Packit c32a2d
#include <fcntl.h>
Packit c32a2d
Packit c32a2d
/* To parse big numbers... */
Packit c32a2d
#ifdef HAVE_ATOLL
Packit c32a2d
#define atobigint atoll
Packit c32a2d
#else
Packit c32a2d
#define atobigint atol
Packit c32a2d
#endif
Packit c32a2d
Packit c32a2d
typedef unsigned char byte;
Packit c32a2d
Packit c32a2d
#if defined(_MSC_VER) && !defined(MPG123_DEF_SSIZE_T)
Packit c32a2d
#define MPG123_DEF_SSIZE_T
Packit c32a2d
#include <stddef.h>
Packit c32a2d
typedef ptrdiff_t ssize_t;
Packit c32a2d
#endif
Packit c32a2d
Packit c32a2d
/* A safe realloc also for very old systems where realloc(NULL, size) returns NULL. */
Packit c32a2d
void *safe_realloc(void *ptr, size_t size);
Packit c32a2d
#ifndef HAVE_STRERROR
Packit c32a2d
const char *strerror(int errnum);
Packit c32a2d
#endif
Packit c32a2d
Packit c32a2d
/* Roll our own strdup() that does not depend on libc feature test macros
Packit c32a2d
   and returns NULL on NULL input instead of crashing. */
Packit c32a2d
char* compat_strdup(const char *s);
Packit c32a2d
Packit c32a2d
/* If we have the size checks enabled, try to derive some sane printfs.
Packit c32a2d
   Simple start: Use max integer type and format if long is not big enough.
Packit c32a2d
   I am hesitating to use %ll without making sure that it's there... */
Packit c32a2d
#if !(defined PLAIN_C89) && (defined SIZEOF_OFF_T) && (SIZEOF_OFF_T > SIZEOF_LONG) && (defined PRIiMAX)
Packit c32a2d
# define OFF_P PRIiMAX
Packit c32a2d
typedef intmax_t off_p;
Packit c32a2d
#else
Packit c32a2d
# define OFF_P "li"
Packit c32a2d
typedef long off_p;
Packit c32a2d
#endif
Packit c32a2d
Packit c32a2d
#if !(defined PLAIN_C89) && (defined SIZEOF_SIZE_T) && (SIZEOF_SIZE_T > SIZEOF_LONG) && (defined PRIuMAX)
Packit c32a2d
# define SIZE_P PRIuMAX
Packit c32a2d
typedef uintmax_t size_p;
Packit c32a2d
#else
Packit c32a2d
# define SIZE_P "lu"
Packit c32a2d
typedef unsigned long size_p;
Packit c32a2d
#endif
Packit c32a2d
Packit c32a2d
#if !(defined PLAIN_C89) && (defined SIZEOF_SSIZE_T) && (SIZEOF_SSIZE_T > SIZEOF_LONG) && (defined PRIiMAX)
Packit c32a2d
# define SSIZE_P PRIuMAX
Packit c32a2d
typedef intmax_t ssize_p;
Packit c32a2d
#else
Packit c32a2d
# define SSIZE_P "li"
Packit c32a2d
typedef long ssize_p;
Packit c32a2d
#endif
Packit c32a2d
Packit c32a2d
/* Get an environment variable, possibly converted to UTF-8 from wide string.
Packit c32a2d
   The return value is a copy that you shall free. */
Packit c32a2d
char *compat_getenv(const char* name);
Packit c32a2d
Packit c32a2d
/**
Packit c32a2d
 * Opening a file handle can be different.
Packit c32a2d
 * This function here is defined to take a path in native encoding (ISO8859 / UTF-8 / ...), or, when MS Windows Unicode support is enabled, an UTF-8 string that will be converted back to native UCS-2 (wide character) before calling the system's open function.
Packit c32a2d
 * @param[in] wptr Pointer to wide string.
Packit c32a2d
 * @param[in] mbptr Pointer to multibyte string.
Packit c32a2d
 * @return file descriptor (>=0) or error code.
Packit c32a2d
 */
Packit c32a2d
int compat_open(const char *filename, int flags);
Packit c32a2d
FILE* compat_fopen(const char *filename, const char *mode);
Packit c32a2d
/**
Packit c32a2d
 * Also fdopen to avoid having to define POSIX macros in various source files.
Packit c32a2d
 */
Packit c32a2d
FILE* compat_fdopen(int fd, const char *mode);
Packit c32a2d
Packit c32a2d
/**
Packit c32a2d
 * Closing a file handle can be platform specific.
Packit c32a2d
 * This function takes a file descriptor that is to be closed.
Packit c32a2d
 * @param[in] infd File descriptor to be closed.
Packit c32a2d
 * @return 0 if the file was successfully closed. A return value of -1 indicates an error.
Packit c32a2d
 */
Packit c32a2d
int compat_close(int infd);
Packit c32a2d
int compat_fclose(FILE* stream);
Packit c32a2d
Packit c32a2d
/* Those do make sense in a separate file, but I chose to include them in compat.c because that's the one source whose object is shared between mpg123 and libmpg123 -- and both need the functionality internally. */
Packit c32a2d
Packit c32a2d
#ifdef WANT_WIN32_UNICODE
Packit c32a2d
/**
Packit c32a2d
 * win32_uni2mbc
Packit c32a2d
 * Converts a null terminated UCS-2 string to a multibyte (UTF-8) equivalent.
Packit c32a2d
 * Caller is supposed to free allocated buffer.
Packit c32a2d
 * @param[in] wptr Pointer to wide string.
Packit c32a2d
 * @param[out] mbptr Pointer to multibyte string.
Packit c32a2d
 * @param[out] buflen Optional parameter for length of allocated buffer.
Packit c32a2d
 * @return status of WideCharToMultiByte conversion.
Packit c32a2d
 *
Packit c32a2d
 * WideCharToMultiByte - http://msdn.microsoft.com/en-us/library/dd374130(VS.85).aspx
Packit c32a2d
 */
Packit c32a2d
int win32_wide_utf8(const wchar_t * const wptr, char **mbptr, size_t * buflen);
Packit c32a2d
Packit c32a2d
/**
Packit c32a2d
 * win32_mbc2uni
Packit c32a2d
 * Converts a null terminated UTF-8 string to a UCS-2 equivalent.
Packit c32a2d
 * Caller is supposed to free allocated buffer.
Packit c32a2d
 * @param[out] mbptr Pointer to multibyte string.
Packit c32a2d
 * @param[in] wptr Pointer to wide string.
Packit c32a2d
 * @param[out] buflen Optional parameter for length of allocated buffer.
Packit c32a2d
 * @return status of WideCharToMultiByte conversion.
Packit c32a2d
 *
Packit c32a2d
 * MultiByteToWideChar - http://msdn.microsoft.com/en-us/library/dd319072(VS.85).aspx
Packit c32a2d
 */
Packit c32a2d
Packit c32a2d
int win32_utf8_wide(const char *const mbptr, wchar_t **wptr, size_t *buflen);
Packit c32a2d
#endif
Packit c32a2d
Packit c32a2d
/*
Packit c32a2d
	A little bit of path abstraction: We always work with plain char strings
Packit c32a2d
	that usually represent POSIX-ish UTF-8 paths (something like c:/some/file
Packit c32a2d
	might appear). For Windows, those are converted to wide strings with \
Packit c32a2d
	instead of / and possible fun is had with prefixes to get around the old
Packit c32a2d
	path length limit. Outside of the compat library, that stuff should not
Packit c32a2d
	matter, although something like //?/UNC/server/some/file could be thrown
Packit c32a2d
	around as UTF-8 string, to be converted to a wide \\?\UNC\server\some\file
Packit c32a2d
	just before handing it to Windows API.
Packit c32a2d
Packit c32a2d
	There is a lot of unnecessary memory allocation and string copying because
Packit c32a2d
	of this, but this filesystem stuff is not really relevant to mpg123
Packit c32a2d
	performance, so the goal is to keep the code outside the compatibility layer
Packit c32a2d
	simple.
Packit c32a2d
*/
Packit c32a2d
Packit c32a2d
/*
Packit c32a2d
	Concatenate a prefix and a path, one of them alowed to be NULL.
Packit c32a2d
	If the path is already absolute, the prefix is ignored. Relative
Packit c32a2d
	parts (like /..) are resolved if this is sensible for the platform
Packit c32a2d
	(meaning: for Windows), else they are preserved (on POSIX, actual
Packit c32a2d
	file system access would be needed because of symlinks).
Packit c32a2d
*/
Packit c32a2d
char* compat_catpath(const char *prefix, const char* path);
Packit c32a2d
Packit c32a2d
/* Return 1 if the given path indicates an existing directory,
Packit c32a2d
   0 otherwise. */
Packit c32a2d
int compat_isdir(const char *path);
Packit c32a2d
Packit c32a2d
/*
Packit c32a2d
	Directory traversal. This talks ASCII/UTF-8 paths externally, converts
Packit c32a2d
	to/from wchar_t internally if the platform wants that. Returning NULL
Packit c32a2d
	means failure to open/end of listing.
Packit c32a2d
	There is no promise about sorting entries.
Packit c32a2d
*/
Packit c32a2d
struct compat_dir;
Packit c32a2d
/* Returns NULL if either directory failed to open or listing is empty.
Packit c32a2d
   Listing can still be empty even if non-NULL, so always rely on the
Packit c32a2d
   nextfile/nextdir functions. */
Packit c32a2d
struct compat_dir* compat_diropen(char *path);
Packit c32a2d
void               compat_dirclose(struct compat_dir*);
Packit c32a2d
/* Get the next entry that is a file (or symlink to one).
Packit c32a2d
   The returned string is a copy that needs to be freed after use. */
Packit c32a2d
char* compat_nextfile(struct compat_dir*);
Packit c32a2d
/* Get the next entry that is a directory (or symlink to one).
Packit c32a2d
   The returned string is a copy that needs to be freed after use. */
Packit c32a2d
char* compat_nextdir (struct compat_dir*);
Packit c32a2d
Packit c32a2d
#ifdef USE_MODULES
Packit c32a2d
/*
Packit c32a2d
	For keeping the path mess local, a system-specific dlopen() variant
Packit c32a2d
	is contained in here, too. This is very thin wrapping, even sparing
Packit c32a2d
	definition of a handle type, just using void pointers.
Packit c32a2d
	Use of absolute paths is a good idea if you want to be sure which
Packit c32a2d
	file is openend, as default search paths vary.
Packit c32a2d
*/
Packit c32a2d
void *compat_dlopen (const char *path);
Packit c32a2d
void *compat_dlsym  (void *handle, const char* name);
Packit c32a2d
void  compat_dlclose(void *handle);
Packit c32a2d
#endif
Packit c32a2d
Packit c32a2d
/* Blocking write/read of data with signal resilience.
Packit c32a2d
   Both continue after being interrupted by signals and always return the
Packit c32a2d
   amount of processed data (shortage indicating actual problem or EOF). */
Packit c32a2d
size_t unintr_write(int fd, void const *buffer, size_t bytes);
Packit c32a2d
size_t unintr_read (int fd, void *buffer, size_t bytes);
Packit c32a2d
Packit c32a2d
/* That one comes from Tellie on OS/2, needed in resolver. */
Packit c32a2d
#ifdef __KLIBC__
Packit c32a2d
typedef int socklen_t;
Packit c32a2d
#endif
Packit c32a2d
Packit c32a2d
/* OSX SDK defines an enum with "normal" as value. That clashes with
Packit c32a2d
   optimize.h */
Packit c32a2d
#ifdef __APPLE__
Packit c32a2d
#define normal mpg123_normal
Packit c32a2d
#endif
Packit c32a2d
Packit c32a2d
#include "true.h"
Packit c32a2d
Packit c32a2d
#if (!defined(WIN32) || defined (__CYGWIN__)) && defined(HAVE_SIGNAL_H)
Packit c32a2d
void (*catchsignal(int signum, void(*handler)()))();
Packit c32a2d
#endif
Packit c32a2d
Packit c32a2d
#endif