compat / mingw.hon commit usage: add set_warn_routine() (b83f108)
   1#ifdef __MINGW64_VERSION_MAJOR
   2#include <stdint.h>
   3#include <wchar.h>
   4typedef _sigset_t sigset_t;
   5#endif
   6#include <winsock2.h>
   7#include <ws2tcpip.h>
   8
   9/* MinGW-w64 reports to have flockfile, but it does not actually have it. */
  10#ifdef __MINGW64_VERSION_MAJOR
  11#undef _POSIX_THREAD_SAFE_FUNCTIONS
  12#endif
  13
  14/*
  15 * things that are not available in header files
  16 */
  17
  18typedef int uid_t;
  19typedef int socklen_t;
  20#ifndef __MINGW64_VERSION_MAJOR
  21typedef int pid_t;
  22#define hstrerror strerror
  23#endif
  24
  25#define S_IFLNK    0120000 /* Symbolic link */
  26#define S_ISLNK(x) (((x) & S_IFMT) == S_IFLNK)
  27#define S_ISSOCK(x) 0
  28
  29#ifndef S_IRWXG
  30#define S_IRGRP 0
  31#define S_IWGRP 0
  32#define S_IXGRP 0
  33#define S_IRWXG (S_IRGRP | S_IWGRP | S_IXGRP)
  34#endif
  35#ifndef S_IRWXO
  36#define S_IROTH 0
  37#define S_IWOTH 0
  38#define S_IXOTH 0
  39#define S_IRWXO (S_IROTH | S_IWOTH | S_IXOTH)
  40#endif
  41
  42#define S_ISUID 0004000
  43#define S_ISGID 0002000
  44#define S_ISVTX 0001000
  45
  46#define WIFEXITED(x) 1
  47#define WIFSIGNALED(x) 0
  48#define WEXITSTATUS(x) ((x) & 0xff)
  49#define WTERMSIG(x) SIGTERM
  50
  51#ifndef EWOULDBLOCK
  52#define EWOULDBLOCK EAGAIN
  53#endif
  54#ifndef ELOOP
  55#define ELOOP EMLINK
  56#endif
  57#define SHUT_WR SD_SEND
  58
  59#define SIGHUP 1
  60#define SIGQUIT 3
  61#define SIGKILL 9
  62#define SIGPIPE 13
  63#define SIGALRM 14
  64#define SIGCHLD 17
  65
  66#define F_GETFD 1
  67#define F_SETFD 2
  68#define FD_CLOEXEC 0x1
  69
  70#ifndef EAFNOSUPPORT
  71#define EAFNOSUPPORT WSAEAFNOSUPPORT
  72#endif
  73#ifndef ECONNABORTED
  74#define ECONNABORTED WSAECONNABORTED
  75#endif
  76#ifndef ENOTSOCK
  77#define ENOTSOCK WSAENOTSOCK
  78#endif
  79
  80struct passwd {
  81        char *pw_name;
  82        char *pw_gecos;
  83        char *pw_dir;
  84};
  85
  86typedef void (__cdecl *sig_handler_t)(int);
  87struct sigaction {
  88        sig_handler_t sa_handler;
  89        unsigned sa_flags;
  90};
  91#define SA_RESTART 0
  92
  93struct itimerval {
  94        struct timeval it_value, it_interval;
  95};
  96#define ITIMER_REAL 0
  97
  98struct utsname {
  99        char sysname[16];
 100        char nodename[1];
 101        char release[16];
 102        char version[16];
 103        char machine[1];
 104};
 105
 106/*
 107 * sanitize preprocessor namespace polluted by Windows headers defining
 108 * macros which collide with git local versions
 109 */
 110#undef HELP_COMMAND /* from winuser.h */
 111
 112/*
 113 * trivial stubs
 114 */
 115
 116static inline int readlink(const char *path, char *buf, size_t bufsiz)
 117{ errno = ENOSYS; return -1; }
 118static inline int symlink(const char *oldpath, const char *newpath)
 119{ errno = ENOSYS; return -1; }
 120static inline int fchmod(int fildes, mode_t mode)
 121{ errno = ENOSYS; return -1; }
 122#ifndef __MINGW64_VERSION_MAJOR
 123static inline pid_t fork(void)
 124{ errno = ENOSYS; return -1; }
 125#endif
 126static inline unsigned int alarm(unsigned int seconds)
 127{ return 0; }
 128static inline int fsync(int fd)
 129{ return _commit(fd); }
 130static inline void sync(void)
 131{}
 132static inline uid_t getuid(void)
 133{ return 1; }
 134static inline struct passwd *getpwnam(const char *name)
 135{ return NULL; }
 136static inline int fcntl(int fd, int cmd, ...)
 137{
 138        if (cmd == F_GETFD || cmd == F_SETFD)
 139                return 0;
 140        errno = EINVAL;
 141        return -1;
 142}
 143/* bash cannot reliably detect negative return codes as failure */
 144#define exit(code) exit((code) & 0xff)
 145#define sigemptyset(x) (void)0
 146static inline int sigaddset(sigset_t *set, int signum)
 147{ return 0; }
 148#define SIG_BLOCK 0
 149#define SIG_UNBLOCK 0
 150static inline int sigprocmask(int how, const sigset_t *set, sigset_t *oldset)
 151{ return 0; }
 152static inline pid_t getppid(void)
 153{ return 1; }
 154static inline pid_t getpgid(pid_t pid)
 155{ return pid == 0 ? getpid() : pid; }
 156static inline pid_t tcgetpgrp(int fd)
 157{ return getpid(); }
 158
 159/*
 160 * simple adaptors
 161 */
 162
 163int mingw_mkdir(const char *path, int mode);
 164#define mkdir mingw_mkdir
 165
 166#define WNOHANG 1
 167pid_t waitpid(pid_t pid, int *status, int options);
 168
 169#define kill mingw_kill
 170int mingw_kill(pid_t pid, int sig);
 171
 172#ifndef NO_OPENSSL
 173#include <openssl/ssl.h>
 174static inline int mingw_SSL_set_fd(SSL *ssl, int fd)
 175{
 176        return SSL_set_fd(ssl, _get_osfhandle(fd));
 177}
 178#define SSL_set_fd mingw_SSL_set_fd
 179
 180static inline int mingw_SSL_set_rfd(SSL *ssl, int fd)
 181{
 182        return SSL_set_rfd(ssl, _get_osfhandle(fd));
 183}
 184#define SSL_set_rfd mingw_SSL_set_rfd
 185
 186static inline int mingw_SSL_set_wfd(SSL *ssl, int fd)
 187{
 188        return SSL_set_wfd(ssl, _get_osfhandle(fd));
 189}
 190#define SSL_set_wfd mingw_SSL_set_wfd
 191#endif
 192
 193/*
 194 * implementations of missing functions
 195 */
 196
 197int pipe(int filedes[2]);
 198unsigned int sleep (unsigned int seconds);
 199int mkstemp(char *template);
 200int gettimeofday(struct timeval *tv, void *tz);
 201#ifndef __MINGW64_VERSION_MAJOR
 202struct tm *gmtime_r(const time_t *timep, struct tm *result);
 203struct tm *localtime_r(const time_t *timep, struct tm *result);
 204#endif
 205int getpagesize(void);  /* defined in MinGW's libgcc.a */
 206struct passwd *getpwuid(uid_t uid);
 207int setitimer(int type, struct itimerval *in, struct itimerval *out);
 208int sigaction(int sig, struct sigaction *in, struct sigaction *out);
 209int link(const char *oldpath, const char *newpath);
 210int uname(struct utsname *buf);
 211
 212/*
 213 * replacements of existing functions
 214 */
 215
 216int mingw_unlink(const char *pathname);
 217#define unlink mingw_unlink
 218
 219int mingw_rmdir(const char *path);
 220#define rmdir mingw_rmdir
 221
 222int mingw_open (const char *filename, int oflags, ...);
 223#define open mingw_open
 224
 225int mingw_fgetc(FILE *stream);
 226#define fgetc mingw_fgetc
 227
 228FILE *mingw_fopen (const char *filename, const char *otype);
 229#define fopen mingw_fopen
 230
 231FILE *mingw_freopen (const char *filename, const char *otype, FILE *stream);
 232#define freopen mingw_freopen
 233
 234int mingw_fflush(FILE *stream);
 235#define fflush mingw_fflush
 236
 237ssize_t mingw_write(int fd, const void *buf, size_t len);
 238#define write mingw_write
 239
 240int mingw_access(const char *filename, int mode);
 241#undef access
 242#define access mingw_access
 243
 244int mingw_chdir(const char *dirname);
 245#define chdir mingw_chdir
 246
 247int mingw_chmod(const char *filename, int mode);
 248#define chmod mingw_chmod
 249
 250char *mingw_mktemp(char *template);
 251#define mktemp mingw_mktemp
 252
 253char *mingw_getcwd(char *pointer, int len);
 254#define getcwd mingw_getcwd
 255
 256char *mingw_getenv(const char *name);
 257#define getenv mingw_getenv
 258int mingw_putenv(const char *namevalue);
 259#define putenv mingw_putenv
 260#define unsetenv mingw_putenv
 261
 262int mingw_gethostname(char *host, int namelen);
 263#define gethostname mingw_gethostname
 264
 265struct hostent *mingw_gethostbyname(const char *host);
 266#define gethostbyname mingw_gethostbyname
 267
 268void mingw_freeaddrinfo(struct addrinfo *res);
 269#define freeaddrinfo mingw_freeaddrinfo
 270
 271int mingw_getaddrinfo(const char *node, const char *service,
 272                      const struct addrinfo *hints, struct addrinfo **res);
 273#define getaddrinfo mingw_getaddrinfo
 274
 275int mingw_getnameinfo(const struct sockaddr *sa, socklen_t salen,
 276                      char *host, DWORD hostlen, char *serv, DWORD servlen,
 277                      int flags);
 278#define getnameinfo mingw_getnameinfo
 279
 280int mingw_socket(int domain, int type, int protocol);
 281#define socket mingw_socket
 282
 283int mingw_connect(int sockfd, struct sockaddr *sa, size_t sz);
 284#define connect mingw_connect
 285
 286int mingw_bind(int sockfd, struct sockaddr *sa, size_t sz);
 287#define bind mingw_bind
 288
 289int mingw_setsockopt(int sockfd, int lvl, int optname, void *optval, int optlen);
 290#define setsockopt mingw_setsockopt
 291
 292int mingw_shutdown(int sockfd, int how);
 293#define shutdown mingw_shutdown
 294
 295int mingw_listen(int sockfd, int backlog);
 296#define listen mingw_listen
 297
 298int mingw_accept(int sockfd, struct sockaddr *sa, socklen_t *sz);
 299#define accept mingw_accept
 300
 301int mingw_rename(const char*, const char*);
 302#define rename mingw_rename
 303
 304#if defined(USE_WIN32_MMAP) || defined(_MSC_VER)
 305int mingw_getpagesize(void);
 306#define getpagesize mingw_getpagesize
 307#endif
 308
 309struct rlimit {
 310        unsigned int rlim_cur;
 311};
 312#define RLIMIT_NOFILE 0
 313
 314static inline int getrlimit(int resource, struct rlimit *rlp)
 315{
 316        if (resource != RLIMIT_NOFILE) {
 317                errno = EINVAL;
 318                return -1;
 319        }
 320
 321        rlp->rlim_cur = 2048;
 322        return 0;
 323}
 324
 325/*
 326 * Use mingw specific stat()/lstat()/fstat() implementations on Windows.
 327 */
 328#ifndef __MINGW64_VERSION_MAJOR
 329#define off_t off64_t
 330#define lseek _lseeki64
 331#endif
 332
 333/* use struct stat with 64 bit st_size */
 334#ifdef stat
 335#undef stat
 336#endif
 337#define stat _stati64
 338int mingw_lstat(const char *file_name, struct stat *buf);
 339int mingw_stat(const char *file_name, struct stat *buf);
 340int mingw_fstat(int fd, struct stat *buf);
 341#ifdef fstat
 342#undef fstat
 343#endif
 344#define fstat mingw_fstat
 345#ifdef lstat
 346#undef lstat
 347#endif
 348#define lstat mingw_lstat
 349
 350#ifndef _stati64
 351# define _stati64(x,y) mingw_stat(x,y)
 352#elif defined (_USE_32BIT_TIME_T)
 353# define _stat32i64(x,y) mingw_stat(x,y)
 354#else
 355# define _stat64(x,y) mingw_stat(x,y)
 356#endif
 357
 358int mingw_utime(const char *file_name, const struct utimbuf *times);
 359#define utime mingw_utime
 360
 361pid_t mingw_spawnvpe(const char *cmd, const char **argv, char **env,
 362                     const char *dir,
 363                     int fhin, int fhout, int fherr);
 364int mingw_execvp(const char *cmd, char *const *argv);
 365#define execvp mingw_execvp
 366int mingw_execv(const char *cmd, char *const *argv);
 367#define execv mingw_execv
 368
 369static inline unsigned int git_ntohl(unsigned int x)
 370{ return (unsigned int)ntohl(x); }
 371#define ntohl git_ntohl
 372
 373sig_handler_t mingw_signal(int sig, sig_handler_t handler);
 374#define signal mingw_signal
 375
 376int mingw_raise(int sig);
 377#define raise mingw_raise
 378
 379/*
 380 * ANSI emulation wrappers
 381 */
 382
 383void winansi_init(void);
 384HANDLE winansi_get_osfhandle(int fd);
 385
 386/*
 387 * git specific compatibility
 388 */
 389
 390#define has_dos_drive_prefix(path) \
 391        (isalpha(*(path)) && (path)[1] == ':' ? 2 : 0)
 392int mingw_skip_dos_drive_prefix(char **path);
 393#define skip_dos_drive_prefix mingw_skip_dos_drive_prefix
 394#define is_dir_sep(c) ((c) == '/' || (c) == '\\')
 395static inline char *mingw_find_last_dir_sep(const char *path)
 396{
 397        char *ret = NULL;
 398        for (; *path; ++path)
 399                if (is_dir_sep(*path))
 400                        ret = (char *)path;
 401        return ret;
 402}
 403static inline void convert_slashes(char *path)
 404{
 405        for (; *path; path++)
 406                if (*path == '\\')
 407                        *path = '/';
 408}
 409#define find_last_dir_sep mingw_find_last_dir_sep
 410int mingw_offset_1st_component(const char *path);
 411#define offset_1st_component mingw_offset_1st_component
 412#define PATH_SEP ';'
 413#if !defined(__MINGW64_VERSION_MAJOR) && (!defined(_MSC_VER) || _MSC_VER < 1800)
 414#define PRIuMAX "I64u"
 415#define PRId64 "I64d"
 416#else
 417#include <inttypes.h>
 418#endif
 419
 420void mingw_open_html(const char *path);
 421#define open_html mingw_open_html
 422
 423/**
 424 * Converts UTF-8 encoded string to UTF-16LE.
 425 *
 426 * To support repositories with legacy-encoded file names, invalid UTF-8 bytes
 427 * 0xa0 - 0xff are converted to corresponding printable Unicode chars \u00a0 -
 428 * \u00ff, and invalid UTF-8 bytes 0x80 - 0x9f (which would make non-printable
 429 * Unicode) are converted to hex-code.
 430 *
 431 * Lead-bytes not followed by an appropriate number of trail-bytes, over-long
 432 * encodings and 4-byte encodings > \u10ffff are detected as invalid UTF-8.
 433 *
 434 * Maximum space requirement for the target buffer is two wide chars per UTF-8
 435 * char (((strlen(utf) * 2) + 1) [* sizeof(wchar_t)]).
 436 *
 437 * The maximum space is needed only if the entire input string consists of
 438 * invalid UTF-8 bytes in range 0x80-0x9f, as per the following table:
 439 *
 440 *               |                   | UTF-8 | UTF-16 |
 441 *   Code point  |  UTF-8 sequence   | bytes | words  | ratio
 442 * --------------+-------------------+-------+--------+-------
 443 * 000000-00007f | 0-7f              |   1   |   1    |  1
 444 * 000080-0007ff | c2-df + 80-bf     |   2   |   1    |  0.5
 445 * 000800-00ffff | e0-ef + 2 * 80-bf |   3   |   1    |  0.33
 446 * 010000-10ffff | f0-f4 + 3 * 80-bf |   4   |  2 (a) |  0.5
 447 * invalid       | 80-9f             |   1   |  2 (b) |  2
 448 * invalid       | a0-ff             |   1   |   1    |  1
 449 *
 450 * (a) encoded as UTF-16 surrogate pair
 451 * (b) encoded as two hex digits
 452 *
 453 * Note that, while the UTF-8 encoding scheme can be extended to 5-byte, 6-byte
 454 * or even indefinite-byte sequences, the largest valid code point \u10ffff
 455 * encodes as only 4 UTF-8 bytes.
 456 *
 457 * Parameters:
 458 * wcs: wide char target buffer
 459 * utf: string to convert
 460 * wcslen: size of target buffer (in wchar_t's)
 461 * utflen: size of string to convert, or -1 if 0-terminated
 462 *
 463 * Returns:
 464 * length of converted string (_wcslen(wcs)), or -1 on failure
 465 *
 466 * Errors:
 467 * EINVAL: one of the input parameters is invalid (e.g. NULL)
 468 * ERANGE: the output buffer is too small
 469 */
 470int xutftowcsn(wchar_t *wcs, const char *utf, size_t wcslen, int utflen);
 471
 472/**
 473 * Simplified variant of xutftowcsn, assumes input string is \0-terminated.
 474 */
 475static inline int xutftowcs(wchar_t *wcs, const char *utf, size_t wcslen)
 476{
 477        return xutftowcsn(wcs, utf, wcslen, -1);
 478}
 479
 480/**
 481 * Simplified file system specific variant of xutftowcsn, assumes output
 482 * buffer size is MAX_PATH wide chars and input string is \0-terminated,
 483 * fails with ENAMETOOLONG if input string is too long.
 484 */
 485static inline int xutftowcs_path(wchar_t *wcs, const char *utf)
 486{
 487        int result = xutftowcsn(wcs, utf, MAX_PATH, -1);
 488        if (result < 0 && errno == ERANGE)
 489                errno = ENAMETOOLONG;
 490        return result;
 491}
 492
 493/**
 494 * Converts UTF-16LE encoded string to UTF-8.
 495 *
 496 * Maximum space requirement for the target buffer is three UTF-8 chars per
 497 * wide char ((_wcslen(wcs) * 3) + 1).
 498 *
 499 * The maximum space is needed only if the entire input string consists of
 500 * UTF-16 words in range 0x0800-0xd7ff or 0xe000-0xffff (i.e. \u0800-\uffff
 501 * modulo surrogate pairs), as per the following table:
 502 *
 503 *               |                       | UTF-16 | UTF-8 |
 504 *   Code point  |  UTF-16 sequence      | words  | bytes | ratio
 505 * --------------+-----------------------+--------+-------+-------
 506 * 000000-00007f | 0000-007f             |   1    |   1   |  1
 507 * 000080-0007ff | 0080-07ff             |   1    |   2   |  2
 508 * 000800-00ffff | 0800-d7ff / e000-ffff |   1    |   3   |  3
 509 * 010000-10ffff | d800-dbff + dc00-dfff |   2    |   4   |  2
 510 *
 511 * Note that invalid code points > 10ffff cannot be represented in UTF-16.
 512 *
 513 * Parameters:
 514 * utf: target buffer
 515 * wcs: wide string to convert
 516 * utflen: size of target buffer
 517 *
 518 * Returns:
 519 * length of converted string, or -1 on failure
 520 *
 521 * Errors:
 522 * EINVAL: one of the input parameters is invalid (e.g. NULL)
 523 * ERANGE: the output buffer is too small
 524 */
 525int xwcstoutf(char *utf, const wchar_t *wcs, size_t utflen);
 526
 527/*
 528 * A critical section used in the implementation of the spawn
 529 * functions (mingw_spawnv[p]e()) and waitpid(). Intialised in
 530 * the replacement main() macro below.
 531 */
 532extern CRITICAL_SECTION pinfo_cs;
 533
 534/*
 535 * A replacement of main() that adds win32 specific initialization.
 536 */
 537
 538void mingw_startup(void);
 539#define main(c,v) dummy_decl_mingw_main(void); \
 540static int mingw_main(c,v); \
 541int main(int argc, const char **argv) \
 542{ \
 543        mingw_startup(); \
 544        return mingw_main(__argc, (void *)__argv); \
 545} \
 546static int mingw_main(c,v)
 547
 548/*
 549 * Used by Pthread API implementation for Windows
 550 */
 551extern int err_win_to_posix(DWORD winerr);