Don't return from overlapped ReadFile on EAGAIN and other non-fatal
[wine/gsoc_dplay.git] / library / port.c
blobb6157b540bf25358d61eafadecd0f0922340f42a
1 /*
2 * Misc. functions for systems that don't have them
4 * Copyright 1996 Alexandre Julliard
5 */
7 #include "config.h"
8 #include "wine/port.h"
10 #ifdef __BEOS__
11 #include <be/kernel/fs_info.h>
12 #include <be/kernel/OS.h>
13 #endif
15 #include <assert.h>
16 #include <ctype.h>
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <unistd.h>
21 #include <sys/types.h>
22 #include <sys/time.h>
23 #include <sys/stat.h>
24 #include <sys/ioctl.h>
25 #include <errno.h>
26 #include <fcntl.h>
27 #include <termios.h>
28 #ifdef HAVE_SYS_MMAN_H
29 #include <sys/mman.h>
30 #endif
31 #ifdef HAVE_LIBIO_H
32 # include <libio.h>
33 #endif
34 #ifdef HAVE_SYSCALL_H
35 # include <syscall.h>
36 #endif
37 #ifdef HAVE_PTY_H
38 # include <pty.h>
39 #endif
40 #ifdef HAVE_LIBUTIL_H
41 # include <libutil.h>
42 #endif
43 #ifdef HAVE_STDINT_H
44 # include <stdint.h>
45 #endif
47 /***********************************************************************
48 * usleep
50 #ifndef HAVE_USLEEP
51 unsigned int usleep (unsigned int useconds)
53 #if defined(__EMX__)
54 DosSleep(useconds);
55 return 0;
56 #elif defined(__BEOS__)
57 return snooze(useconds);
58 #elif defined(HAVE_SELECT)
59 struct timeval delay;
61 delay.tv_sec = useconds / 1000000;
62 delay.tv_usec = useconds % 1000000;
64 select( 0, 0, 0, 0, &delay );
65 return 0;
66 #else /* defined(__EMX__) || defined(__BEOS__) || defined(HAVE_SELECT) */
67 errno = ENOSYS;
68 return -1;
69 #endif /* defined(__EMX__) || defined(__BEOS__) || defined(HAVE_SELECT) */
71 #endif /* HAVE_USLEEP */
73 /***********************************************************************
74 * memmove
76 #ifndef HAVE_MEMMOVE
77 void *memmove( void *dest, const void *src, unsigned int len )
79 register char *dst = dest;
81 /* Use memcpy if not overlapping */
82 if ((dst + len <= (char *)src) || ((char *)src + len <= dst))
84 memcpy( dst, src, len );
86 /* Otherwise do it the hard way (FIXME: could do better than this) */
87 else if (dst < src)
89 while (len--) *dst++ = *((char *)src)++;
91 else
93 dst += len - 1;
94 src = (char *)src + len - 1;
95 while (len--) *dst-- = *((char *)src)--;
97 return dest;
99 #endif /* HAVE_MEMMOVE */
101 /***********************************************************************
102 * strerror
104 #ifndef HAVE_STRERROR
105 const char *strerror( int err )
107 /* Let's hope we have sys_errlist then */
108 return sys_errlist[err];
110 #endif /* HAVE_STRERROR */
113 /***********************************************************************
114 * getpagesize
116 #ifndef HAVE_GETPAGESIZE
117 size_t getpagesize(void)
119 # ifdef __svr4__
120 return sysconf(_SC_PAGESIZE);
121 # else
122 # error Cannot get the page size on this platform
123 # endif
125 #endif /* HAVE_GETPAGESIZE */
128 /***********************************************************************
129 * clone
131 #if !defined(HAVE_CLONE) && defined(__linux__)
132 int clone( int (*fn)(void *), void *stack, int flags, void *arg )
134 #ifdef __i386__
135 int ret;
136 void **stack_ptr = (void **)stack;
137 *--stack_ptr = arg; /* Push argument on stack */
138 *--stack_ptr = fn; /* Push function pointer (popped into ebx) */
139 __asm__ __volatile__( "pushl %%ebx\n\t"
140 "movl %2,%%ebx\n\t"
141 "int $0x80\n\t"
142 "popl %%ebx\n\t" /* Contains fn in the child */
143 "testl %%eax,%%eax\n\t"
144 "jnz 0f\n\t"
145 "xorl %ebp,%ebp\n\t" /* Terminate the stack frames */
146 "call *%%ebx\n\t" /* Should never return */
147 "xorl %%eax,%%eax\n\t" /* Just in case it does*/
148 "0:"
149 : "=a" (ret)
150 : "0" (SYS_clone), "r" (flags), "c" (stack_ptr) );
151 assert( ret ); /* If ret is 0, we returned from the child function */
152 if (ret > 0) return ret;
153 errno = -ret;
154 return -1;
155 #else
156 errno = EINVAL;
157 return -1;
158 #endif /* __i386__ */
160 #endif /* !HAVE_CLONE && __linux__ */
162 /***********************************************************************
163 * strcasecmp
165 #ifndef HAVE_STRCASECMP
166 int strcasecmp( const char *str1, const char *str2 )
168 const unsigned char *ustr1 = (const unsigned char *)str1;
169 const unsigned char *ustr2 = (const unsigned char *)str2;
171 while (*ustr1 && toupper(*ustr1) == toupper(*ustr2)) {
172 ustr1++;
173 ustr2++;
175 return toupper(*ustr1) - toupper(*ustr2);
177 #endif /* HAVE_STRCASECMP */
179 /***********************************************************************
180 * strncasecmp
182 #ifndef HAVE_STRNCASECMP
183 int strncasecmp( const char *str1, const char *str2, size_t n )
185 const unsigned char *ustr1 = (const unsigned char *)str1;
186 const unsigned char *ustr2 = (const unsigned char *)str2;
187 int res;
189 if (!n) return 0;
190 while ((--n > 0) && *ustr1) {
191 if ((res = toupper(*ustr1) - toupper(*ustr2))) return res;
192 ustr1++;
193 ustr2++;
195 return toupper(*ustr1) - toupper(*ustr2);
197 #endif /* HAVE_STRNCASECMP */
199 /***********************************************************************
200 * wine_openpty
201 * NOTE
202 * It looks like the openpty that comes with glibc in RedHat 5.0
203 * is buggy (second call returns what looks like a dup of 0 and 1
204 * instead of a new pty), this is a generic replacement.
206 * FIXME
207 * We should have a autoconf check for this.
209 int wine_openpty(int *master, int *slave, char *name,
210 struct termios *term, struct winsize *winsize)
212 #ifdef HAVE_OPENPTY
213 return openpty(master, slave, name, term, winsize);
214 #else
215 const char *ptr1, *ptr2;
216 char pts_name[512];
218 strcpy (pts_name, "/dev/ptyXY");
220 for (ptr1 = "pqrstuvwxyzPQRST"; *ptr1 != 0; ptr1++) {
221 pts_name[8] = *ptr1;
222 for (ptr2 = "0123456789abcdef"; *ptr2 != 0; ptr2++) {
223 pts_name[9] = *ptr2;
225 if ((*master = open(pts_name, O_RDWR)) < 0) {
226 if (errno == ENOENT)
227 return -1;
228 else
229 continue;
231 pts_name[5] = 't';
232 if ((*slave = open(pts_name, O_RDWR)) < 0) {
233 pts_name[5] = 'p';
234 close (*master);
235 continue;
238 if (term != NULL)
239 tcsetattr(*slave, TCSANOW, term);
240 if (winsize != NULL)
241 ioctl(*slave, TIOCSWINSZ, winsize);
242 if (name != NULL)
243 strcpy(name, pts_name);
244 return *slave;
247 errno = EMFILE;
248 return -1;
249 #endif
252 /***********************************************************************
253 * getnetbyaddr
255 #ifndef HAVE_GETNETBYADDR
256 struct netent *getnetbyaddr(unsigned long net, int type)
258 errno = ENOSYS;
259 return NULL;
261 #endif /* defined(HAVE_GETNETBYNAME) */
263 /***********************************************************************
264 * getnetbyname
266 #ifndef HAVE_GETNETBYNAME
267 struct netent *getnetbyname(const char *name)
269 errno = ENOSYS;
270 return NULL;
272 #endif /* defined(HAVE_GETNETBYNAME) */
274 /***********************************************************************
275 * getprotobyname
277 #ifndef HAVE_GETPROTOBYNAME
278 struct protoent *getprotobyname(const char *name)
280 errno = ENOSYS;
281 return NULL;
283 #endif /* !defined(HAVE_GETPROTOBYNAME) */
285 /***********************************************************************
286 * getprotobynumber
288 #ifndef HAVE_GETPROTOBYNUMBER
289 struct protoent *getprotobynumber(int proto)
291 errno = ENOSYS;
292 return NULL;
294 #endif /* !defined(HAVE_GETPROTOBYNUMBER) */
296 /***********************************************************************
297 * getservbyport
299 #ifndef HAVE_GETSERVBYPORT
300 struct servent *getservbyport(int port, const char *proto)
302 errno = ENOSYS;
303 return NULL;
305 #endif /* !defined(HAVE_GETSERVBYPORT) */
307 /***********************************************************************
308 * getsockopt
310 #ifndef HAVE_GETSOCKOPT
311 int getsockopt(int socket, int level, int option_name,
312 void *option_value, size_t *option_len)
314 errno = ENOSYS;
315 return -1;
317 #endif /* !defined(HAVE_GETSOCKOPT) */
319 /***********************************************************************
320 * inet_network
322 #ifndef HAVE_INET_NETWORK
323 unsigned long inet_network(const char *cp)
325 errno = ENOSYS;
326 return 0;
328 #endif /* defined(HAVE_INET_NETWORK) */
330 /***********************************************************************
331 * settimeofday
333 #ifndef HAVE_SETTIMEOFDAY
334 int settimeofday(struct timeval *tp, void *reserved)
336 tp->tv_sec = 0;
337 tp->tv_usec = 0;
339 errno = ENOSYS;
340 return -1;
342 #endif /* HAVE_SETTIMEOFDAY */
344 /***********************************************************************
345 * statfs
347 #ifndef HAVE_STATFS
348 int statfs(const char *name, struct statfs *info)
350 #ifdef __BEOS__
351 dev_t mydev;
352 fs_info fsinfo;
354 if(!info) {
355 errno = ENOSYS;
356 return -1;
359 if ((mydev = dev_for_path(name)) < 0) {
360 errno = ENOSYS;
361 return -1;
364 if (fs_stat_dev(mydev,&fsinfo) < 0) {
365 errno = ENOSYS;
366 return -1;
369 info->f_bsize = fsinfo.block_size;
370 info->f_blocks = fsinfo.total_blocks;
371 info->f_bfree = fsinfo.free_blocks;
372 return 0;
373 #else /* defined(__BEOS__) */
374 errno = ENOSYS;
375 return -1;
376 #endif /* defined(__BEOS__) */
378 #endif /* !defined(HAVE_STATFS) */
381 /***********************************************************************
382 * lstat
384 #ifndef HAVE_LSTAT
385 int lstat(const char *file_name, struct stat *buf)
387 return stat( file_name, buf );
389 #endif /* HAVE_LSTAT */
391 /***********************************************************************
392 * getrlimit
394 #ifndef HAVE_GETRLIMIT
395 int getrlimit (int resource, struct rlimit *rlim)
397 return -1; /* FAIL */
399 #endif /* HAVE_GETRLIMIT */
402 #if defined(__svr4__) || defined(__NetBSD__)
403 /***********************************************************************
404 * try_mmap_fixed
406 * The purpose of this routine is to emulate the behaviour of
407 * the Linux mmap() routine if a non-NULL address is passed,
408 * but the MAP_FIXED flag is not set. Linux in this case tries
409 * to place the mapping at the specified address, *unless* the
410 * range is already in use. Solaris, however, completely ignores
411 * the address argument in this case.
413 * As Wine code occasionally relies on the Linux behaviour, e.g. to
414 * be able to map non-relocateable PE executables to their proper
415 * start addresses, or to map the DOS memory to 0, this routine
416 * emulates the Linux behaviour by checking whether the desired
417 * address range is still available, and placing the mapping there
418 * using MAP_FIXED if so.
420 static int try_mmap_fixed (void *addr, size_t len, int prot, int flags,
421 int fildes, off_t off)
423 char * volatile result = NULL;
424 int pagesize = getpagesize();
425 pid_t pid;
427 /* We only try to map to a fixed address if
428 addr is non-NULL and properly aligned,
429 and MAP_FIXED isn't already specified. */
431 if ( !addr )
432 return 0;
433 if ( (uintptr_t)addr & (pagesize-1) )
434 return 0;
435 if ( flags & MAP_FIXED )
436 return 0;
438 /* We use vfork() to freeze all threads of the
439 current process. This allows us to check without
440 race condition whether the desired memory range is
441 already in use. Note that because vfork() shares
442 the address spaces between parent and child, we
443 can actually perform the mapping in the child. */
445 if ( (pid = vfork()) == -1 )
447 perror("try_mmap_fixed: vfork");
448 exit(1);
450 if ( pid == 0 )
452 int i;
453 char vec;
455 /* We call mincore() for every page in the desired range.
456 If any of these calls succeeds, the page is already
457 mapped and we must fail. */
458 for ( i = 0; i < len; i += pagesize )
459 if ( mincore( (caddr_t)addr + i, pagesize, &vec ) != -1 )
460 _exit(1);
462 /* Perform the mapping with MAP_FIXED set. This is safe
463 now, as none of the pages is currently in use. */
464 result = mmap( addr, len, prot, flags | MAP_FIXED, fildes, off );
465 if ( result == addr )
466 _exit(0);
468 if ( result != (void *) -1 ) /* This should never happen ... */
469 munmap( result, len );
471 _exit(1);
474 /* vfork() lets the parent continue only after the child
475 has exited. Furthermore, Wine sets SIGCHLD to SIG_IGN,
476 so we don't need to wait for the child. */
478 return result == addr;
480 #endif
482 /***********************************************************************
483 * wine_anon_mmap
485 * Portable wrapper for anonymous mmaps
487 void *wine_anon_mmap( void *start, size_t size, int prot, int flags )
489 static int fdzero = -1;
491 #ifdef MAP_ANON
492 flags |= MAP_ANON;
493 #else
494 if (fdzero == -1)
496 if ((fdzero = open( "/dev/zero", O_RDONLY )) == -1)
498 perror( "/dev/zero: open" );
499 exit(1);
502 #endif /* MAP_ANON */
504 #ifdef MAP_SHARED
505 flags &= ~MAP_SHARED;
506 #endif
508 /* Linux EINVAL's on us if we don't pass MAP_PRIVATE to an anon mmap */
509 #ifdef MAP_PRIVATE
510 flags |= MAP_PRIVATE;
511 #endif
513 #if defined(__svr4__) || defined(__NetBSD__)
514 if ( try_mmap_fixed( start, size, prot, flags, fdzero, 0 ) )
515 return start;
516 #endif
518 return mmap( start, size, prot, flags, fdzero, 0 );
523 * These functions provide wrappers around dlopen() and associated
524 * functions. They work around a bug in glibc 2.1.x where calling
525 * a dl*() function after a previous dl*() function has failed
526 * without a dlerror() call between the two will cause a crash.
527 * They all take a pointer to a buffer that
528 * will receive the error description (from dlerror()). This
529 * parameter may be NULL if the error description is not required.
532 /***********************************************************************
533 * wine_dlopen
535 void *wine_dlopen( const char *filename, int flag, char *error, int errorsize )
537 #ifdef HAVE_DLOPEN
538 void *ret;
539 char *s;
540 dlerror(); dlerror();
541 ret = dlopen( filename, flag );
542 s = dlerror();
543 if (error)
545 strncpy( error, s ? s : "", errorsize );
546 error[errorsize - 1] = '\0';
548 dlerror();
549 return ret;
550 #else
551 if (error)
553 strncpy( error, "dlopen interface not detected by configure", errorsize );
554 error[errorsize - 1] = '\0';
556 return NULL;
557 #endif
560 /***********************************************************************
561 * wine_dlsym
563 void *wine_dlsym( void *handle, const char *symbol, char *error, int errorsize )
565 #ifdef HAVE_DLOPEN
566 void *ret;
567 char *s;
568 dlerror(); dlerror();
569 ret = dlsym( handle, symbol );
570 s = dlerror();
571 if (error)
573 strncpy( error, s ? s : "", errorsize );
574 error[errorsize - 1] = '\0';
576 dlerror();
577 return ret;
578 #else
579 if (error)
581 strncpy( error, "dlopen interface not detected by configure", errorsize );
582 error[errorsize - 1] = '\0';
584 return NULL;
585 #endif
588 /***********************************************************************
589 * wine_dlclose
591 int wine_dlclose( void *handle, char *error, int errorsize )
593 #ifdef HAVE_DLOPEN
594 int ret;
595 char *s;
596 dlerror(); dlerror();
597 ret = dlclose( handle );
598 s = dlerror();
599 if (error)
601 strncpy( error, s ? s : "", errorsize );
602 error[errorsize - 1] = '\0';
604 dlerror();
605 return ret;
606 #else
607 if (error)
609 strncpy( error, "dlopen interface not detected by configure", errorsize );
610 error[errorsize - 1] = '\0';
612 return 1;
613 #endif
616 /***********************************************************************
617 * wine_rewrite_s4tos2
619 * Convert 4 byte Unicode strings to 2 byte Unicode strings in-place.
620 * This is only practical if literal strings are writable.
622 unsigned short* wine_rewrite_s4tos2(const wchar_t* str4 )
624 unsigned short *str2,*s2;
626 if (str4==NULL)
627 return NULL;
629 if ((*str4 & 0xffff0000) != 0) {
630 /* This string has already been converted. Return it as is */
631 return (unsigned short*)str4;
634 /* Note that we can also end up here if the string has a single
635 * character. In such a case we will convert the string over and
636 * over again. But this is harmless.
638 str2=s2=(unsigned short*)str4;
639 do {
640 *s2=(unsigned short)*str4;
641 s2++;
642 } while (*str4++ != L'\0');
644 return str2;
647 #ifndef HAVE_ECVT
649 * NetBSD 1.5 doesn't have ecvt, fcvt, gcvt. We just check for ecvt, though.
650 * Fix/verify these implementations !
653 /***********************************************************************
654 * ecvt
656 char *ecvt (double number, int ndigits, int *decpt, int *sign)
658 static char buf[40]; /* ought to be enough */
659 char *dec;
660 sprintf(buf, "%.*e", ndigits /* FIXME wrong */, number);
661 *sign = (number < 0);
662 dec = strchr(buf, '.');
663 *decpt = (dec) ? (int)dec - (int)buf : -1;
664 return buf;
667 /***********************************************************************
668 * fcvt
670 char *fcvt (double number, int ndigits, int *decpt, int *sign)
672 static char buf[40]; /* ought to be enough */
673 char *dec;
674 sprintf(buf, "%.*e", ndigits, number);
675 *sign = (number < 0);
676 dec = strchr(buf, '.');
677 *decpt = (dec) ? (int)dec - (int)buf : -1;
678 return buf;
681 /***********************************************************************
682 * gcvt
684 * FIXME: uses both E and F.
686 char *gcvt (double number, size_t ndigit, char *buff)
688 sprintf(buff, "%.*E", (int)ndigit, number);
689 return buff;
691 #endif /* HAVE_ECVT */