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