When freeing XMS memory block, return an error if block has not been
[wine/multimedia.git] / library / port.c
blob37e7dd92ed0c70f464a6933bcf9639ad0dfa9d26
1 /*
2 * Misc. functions for systems that don't have them
4 * Copyright 1996 Alexandre Julliard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include "config.h"
22 #include "wine/port.h"
24 #ifdef __BEOS__
25 #include <be/kernel/fs_info.h>
26 #include <be/kernel/OS.h>
27 #endif
29 #include <assert.h>
30 #include <ctype.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <unistd.h>
35 #include <sys/types.h>
36 #ifdef HAVE_SYS_INTTYPES_H
37 # include <sys/inttypes.h>
38 #endif
39 #ifdef HAVE_SYS_TIME_h
40 # include <sys/time.h>
41 #endif
42 #include <sys/stat.h>
43 #include <sys/ioctl.h>
44 #include <errno.h>
45 #include <fcntl.h>
46 #include <termios.h>
47 #ifdef HAVE_SYS_MMAN_H
48 #include <sys/mman.h>
49 #endif
50 #ifdef HAVE_LIBIO_H
51 # include <libio.h>
52 #endif
53 #ifdef HAVE_SYSCALL_H
54 # include <syscall.h>
55 #endif
56 #ifdef HAVE_STDINT_H
57 # include <stdint.h>
58 #endif
60 /***********************************************************************
61 * usleep
63 #ifndef HAVE_USLEEP
64 unsigned int usleep (unsigned int useconds)
66 #if defined(__EMX__)
67 DosSleep(useconds);
68 return 0;
69 #elif defined(__BEOS__)
70 return snooze(useconds);
71 #elif defined(HAVE_SELECT)
72 struct timeval delay;
74 delay.tv_sec = useconds / 1000000;
75 delay.tv_usec = useconds % 1000000;
77 select( 0, 0, 0, 0, &delay );
78 return 0;
79 #else /* defined(__EMX__) || defined(__BEOS__) || defined(HAVE_SELECT) */
80 errno = ENOSYS;
81 return -1;
82 #endif /* defined(__EMX__) || defined(__BEOS__) || defined(HAVE_SELECT) */
84 #endif /* HAVE_USLEEP */
86 /***********************************************************************
87 * memmove
89 #ifndef HAVE_MEMMOVE
90 void *memmove( void *dest, const void *src, unsigned int len )
92 register char *dst = dest;
94 /* Use memcpy if not overlapping */
95 if ((dst + len <= (char *)src) || ((char *)src + len <= dst))
97 memcpy( dst, src, len );
99 /* Otherwise do it the hard way (FIXME: could do better than this) */
100 else if (dst < src)
102 while (len--) *dst++ = *((char *)src)++;
104 else
106 dst += len - 1;
107 src = (char *)src + len - 1;
108 while (len--) *dst-- = *((char *)src)--;
110 return dest;
112 #endif /* HAVE_MEMMOVE */
114 /***********************************************************************
115 * strerror
117 #ifndef HAVE_STRERROR
118 const char *strerror( int err )
120 /* Let's hope we have sys_errlist then */
121 return sys_errlist[err];
123 #endif /* HAVE_STRERROR */
126 /***********************************************************************
127 * getpagesize
129 #ifndef HAVE_GETPAGESIZE
130 size_t getpagesize(void)
132 # ifdef __svr4__
133 return sysconf(_SC_PAGESIZE);
134 # else
135 # error Cannot get the page size on this platform
136 # endif
138 #endif /* HAVE_GETPAGESIZE */
141 /***********************************************************************
142 * clone
144 #if !defined(HAVE_CLONE) && defined(__linux__)
145 int clone( int (*fn)(void *), void *stack, int flags, void *arg )
147 #ifdef __i386__
148 int ret;
149 void **stack_ptr = (void **)stack;
150 *--stack_ptr = arg; /* Push argument on stack */
151 *--stack_ptr = fn; /* Push function pointer (popped into ebx) */
152 __asm__ __volatile__( "pushl %%ebx\n\t"
153 "movl %2,%%ebx\n\t"
154 "int $0x80\n\t"
155 "popl %%ebx\n\t" /* Contains fn in the child */
156 "testl %%eax,%%eax\n\t"
157 "jnz 0f\n\t"
158 "xorl %ebp,%ebp\n\t" /* Terminate the stack frames */
159 "call *%%ebx\n\t" /* Should never return */
160 "xorl %%eax,%%eax\n\t" /* Just in case it does*/
161 "0:"
162 : "=a" (ret)
163 : "0" (SYS_clone), "r" (flags), "c" (stack_ptr) );
164 assert( ret ); /* If ret is 0, we returned from the child function */
165 if (ret > 0) return ret;
166 errno = -ret;
167 return -1;
168 #else
169 errno = EINVAL;
170 return -1;
171 #endif /* __i386__ */
173 #endif /* !HAVE_CLONE && __linux__ */
175 /***********************************************************************
176 * strcasecmp
178 #ifndef HAVE_STRCASECMP
179 int strcasecmp( const char *str1, const char *str2 )
181 const unsigned char *ustr1 = (const unsigned char *)str1;
182 const unsigned char *ustr2 = (const unsigned char *)str2;
184 while (*ustr1 && toupper(*ustr1) == toupper(*ustr2)) {
185 ustr1++;
186 ustr2++;
188 return toupper(*ustr1) - toupper(*ustr2);
190 #endif /* HAVE_STRCASECMP */
192 /***********************************************************************
193 * strncasecmp
195 #ifndef HAVE_STRNCASECMP
196 int strncasecmp( const char *str1, const char *str2, size_t n )
198 const unsigned char *ustr1 = (const unsigned char *)str1;
199 const unsigned char *ustr2 = (const unsigned char *)str2;
200 int res;
202 if (!n) return 0;
203 while ((--n > 0) && *ustr1) {
204 if ((res = toupper(*ustr1) - toupper(*ustr2))) return res;
205 ustr1++;
206 ustr2++;
208 return toupper(*ustr1) - toupper(*ustr2);
210 #endif /* HAVE_STRNCASECMP */
212 /***********************************************************************
213 * getnetbyaddr
215 #ifndef HAVE_GETNETBYADDR
216 struct netent *getnetbyaddr(unsigned long net, int type)
218 errno = ENOSYS;
219 return NULL;
221 #endif /* defined(HAVE_GETNETBYNAME) */
223 /***********************************************************************
224 * getnetbyname
226 #ifndef HAVE_GETNETBYNAME
227 struct netent *getnetbyname(const char *name)
229 errno = ENOSYS;
230 return NULL;
232 #endif /* defined(HAVE_GETNETBYNAME) */
234 /***********************************************************************
235 * getprotobyname
237 #ifndef HAVE_GETPROTOBYNAME
238 struct protoent *getprotobyname(const char *name)
240 errno = ENOSYS;
241 return NULL;
243 #endif /* !defined(HAVE_GETPROTOBYNAME) */
245 /***********************************************************************
246 * getprotobynumber
248 #ifndef HAVE_GETPROTOBYNUMBER
249 struct protoent *getprotobynumber(int proto)
251 errno = ENOSYS;
252 return NULL;
254 #endif /* !defined(HAVE_GETPROTOBYNUMBER) */
256 /***********************************************************************
257 * getservbyport
259 #ifndef HAVE_GETSERVBYPORT
260 struct servent *getservbyport(int port, const char *proto)
262 errno = ENOSYS;
263 return NULL;
265 #endif /* !defined(HAVE_GETSERVBYPORT) */
267 /***********************************************************************
268 * getsockopt
270 #ifndef HAVE_GETSOCKOPT
271 int getsockopt(int socket, int level, int option_name,
272 void *option_value, size_t *option_len)
274 errno = ENOSYS;
275 return -1;
277 #endif /* !defined(HAVE_GETSOCKOPT) */
279 /***********************************************************************
280 * inet_network
282 #ifndef HAVE_INET_NETWORK
283 unsigned long inet_network(const char *cp)
285 errno = ENOSYS;
286 return 0;
288 #endif /* defined(HAVE_INET_NETWORK) */
290 /***********************************************************************
291 * statfs
293 #ifndef HAVE_STATFS
294 int statfs(const char *name, struct statfs *info)
296 #ifdef __BEOS__
297 dev_t mydev;
298 fs_info fsinfo;
300 if(!info) {
301 errno = ENOSYS;
302 return -1;
305 if ((mydev = dev_for_path(name)) < 0) {
306 errno = ENOSYS;
307 return -1;
310 if (fs_stat_dev(mydev,&fsinfo) < 0) {
311 errno = ENOSYS;
312 return -1;
315 info->f_bsize = fsinfo.block_size;
316 info->f_blocks = fsinfo.total_blocks;
317 info->f_bfree = fsinfo.free_blocks;
318 return 0;
319 #else /* defined(__BEOS__) */
320 errno = ENOSYS;
321 return -1;
322 #endif /* defined(__BEOS__) */
324 #endif /* !defined(HAVE_STATFS) */
327 /***********************************************************************
328 * lstat
330 #ifndef HAVE_LSTAT
331 int lstat(const char *file_name, struct stat *buf)
333 return stat( file_name, buf );
335 #endif /* HAVE_LSTAT */
338 /***********************************************************************
339 * pread
341 * FIXME: this is not thread-safe
343 #ifndef HAVE_PREAD
344 ssize_t pread( int fd, void *buf, size_t count, off_t offset )
346 ssize_t ret;
347 off_t old_pos;
349 if ((old_pos = lseek( fd, 0, SEEK_CUR )) == -1) return -1;
350 if (lseek( fd, offset, SEEK_SET ) == -1) return -1;
351 if ((ret = read( fd, buf, count )) == -1)
353 int err = errno; /* save errno */
354 lseek( fd, old_pos, SEEK_SET );
355 errno = err;
356 return -1;
358 if (lseek( fd, old_pos, SEEK_SET ) == -1) return -1;
359 return ret;
361 #endif /* HAVE_PREAD */
364 /***********************************************************************
365 * pwrite
367 * FIXME: this is not thread-safe
369 #ifndef HAVE_PWRITE
370 ssize_t pwrite( int fd, const void *buf, size_t count, off_t offset )
372 ssize_t ret;
373 off_t old_pos;
375 if ((old_pos = lseek( fd, 0, SEEK_CUR )) == -1) return -1;
376 if (lseek( fd, offset, SEEK_SET ) == -1) return -1;
377 if ((ret = write( fd, buf, count )) == -1)
379 int err = errno; /* save errno */
380 lseek( fd, old_pos, SEEK_SET );
381 errno = err;
382 return -1;
384 if (lseek( fd, old_pos, SEEK_SET ) == -1) return -1;
385 return ret;
387 #endif /* HAVE_PWRITE */
390 #if defined(__svr4__) || defined(__NetBSD__)
391 /***********************************************************************
392 * try_mmap_fixed
394 * The purpose of this routine is to emulate the behaviour of
395 * the Linux mmap() routine if a non-NULL address is passed,
396 * but the MAP_FIXED flag is not set. Linux in this case tries
397 * to place the mapping at the specified address, *unless* the
398 * range is already in use. Solaris, however, completely ignores
399 * the address argument in this case.
401 * As Wine code occasionally relies on the Linux behaviour, e.g. to
402 * be able to map non-relocateable PE executables to their proper
403 * start addresses, or to map the DOS memory to 0, this routine
404 * emulates the Linux behaviour by checking whether the desired
405 * address range is still available, and placing the mapping there
406 * using MAP_FIXED if so.
408 static int try_mmap_fixed (void *addr, size_t len, int prot, int flags,
409 int fildes, off_t off)
411 char * volatile result = NULL;
412 int pagesize = getpagesize();
413 pid_t pid;
415 /* We only try to map to a fixed address if
416 addr is non-NULL and properly aligned,
417 and MAP_FIXED isn't already specified. */
419 if ( !addr )
420 return 0;
421 if ( (uintptr_t)addr & (pagesize-1) )
422 return 0;
423 if ( flags & MAP_FIXED )
424 return 0;
426 /* We use vfork() to freeze all threads of the
427 current process. This allows us to check without
428 race condition whether the desired memory range is
429 already in use. Note that because vfork() shares
430 the address spaces between parent and child, we
431 can actually perform the mapping in the child. */
433 if ( (pid = vfork()) == -1 )
435 perror("try_mmap_fixed: vfork");
436 exit(1);
438 if ( pid == 0 )
440 int i;
441 char vec;
443 /* We call mincore() for every page in the desired range.
444 If any of these calls succeeds, the page is already
445 mapped and we must fail. */
446 for ( i = 0; i < len; i += pagesize )
447 if ( mincore( (caddr_t)addr + i, pagesize, &vec ) != -1 )
448 _exit(1);
450 /* Perform the mapping with MAP_FIXED set. This is safe
451 now, as none of the pages is currently in use. */
452 result = mmap( addr, len, prot, flags | MAP_FIXED, fildes, off );
453 if ( result == addr )
454 _exit(0);
456 if ( result != (void *) -1 ) /* This should never happen ... */
457 munmap( result, len );
459 _exit(1);
462 /* vfork() lets the parent continue only after the child
463 has exited. Furthermore, Wine sets SIGCHLD to SIG_IGN,
464 so we don't need to wait for the child. */
466 return result == addr;
468 #endif
470 /***********************************************************************
471 * wine_anon_mmap
473 * Portable wrapper for anonymous mmaps
475 void *wine_anon_mmap( void *start, size_t size, int prot, int flags )
477 static int fdzero = -1;
479 #ifdef MAP_ANON
480 flags |= MAP_ANON;
481 #else
482 if (fdzero == -1)
484 if ((fdzero = open( "/dev/zero", O_RDONLY )) == -1)
486 perror( "/dev/zero: open" );
487 exit(1);
490 #endif /* MAP_ANON */
492 #ifdef MAP_SHARED
493 flags &= ~MAP_SHARED;
494 #endif
496 /* Linux EINVAL's on us if we don't pass MAP_PRIVATE to an anon mmap */
497 #ifdef MAP_PRIVATE
498 flags |= MAP_PRIVATE;
499 #endif
501 #if defined(__svr4__) || defined(__NetBSD__)
502 if ( try_mmap_fixed( start, size, prot, flags, fdzero, 0 ) )
503 return start;
504 #endif
506 return mmap( start, size, prot, flags, fdzero, 0 );
511 * These functions provide wrappers around dlopen() and associated
512 * functions. They work around a bug in glibc 2.1.x where calling
513 * a dl*() function after a previous dl*() function has failed
514 * without a dlerror() call between the two will cause a crash.
515 * They all take a pointer to a buffer that
516 * will receive the error description (from dlerror()). This
517 * parameter may be NULL if the error description is not required.
520 /***********************************************************************
521 * wine_dlopen
523 void *wine_dlopen( const char *filename, int flag, char *error, int errorsize )
525 #ifdef HAVE_DLOPEN
526 void *ret;
527 const char *s;
528 dlerror(); dlerror();
529 ret = dlopen( filename, flag );
530 s = dlerror();
531 if (error)
533 strncpy( error, s ? s : "", errorsize );
534 error[errorsize - 1] = '\0';
536 dlerror();
537 return ret;
538 #else
539 if (error)
541 strncpy( error, "dlopen interface not detected by configure", errorsize );
542 error[errorsize - 1] = '\0';
544 return NULL;
545 #endif
548 /***********************************************************************
549 * wine_dlsym
551 void *wine_dlsym( void *handle, const char *symbol, char *error, int errorsize )
553 #ifdef HAVE_DLOPEN
554 void *ret;
555 const char *s;
556 dlerror(); dlerror();
557 ret = dlsym( handle, symbol );
558 s = dlerror();
559 if (error)
561 strncpy( error, s ? s : "", errorsize );
562 error[errorsize - 1] = '\0';
564 dlerror();
565 return ret;
566 #else
567 if (error)
569 strncpy( error, "dlopen interface not detected by configure", errorsize );
570 error[errorsize - 1] = '\0';
572 return NULL;
573 #endif
576 /***********************************************************************
577 * wine_dlclose
579 int wine_dlclose( void *handle, char *error, int errorsize )
581 #ifdef HAVE_DLOPEN
582 int ret;
583 const char *s;
584 dlerror(); dlerror();
585 ret = dlclose( handle );
586 s = dlerror();
587 if (error)
589 strncpy( error, s ? s : "", errorsize );
590 error[errorsize - 1] = '\0';
592 dlerror();
593 return ret;
594 #else
595 if (error)
597 strncpy( error, "dlopen interface not detected by configure", errorsize );
598 error[errorsize - 1] = '\0';
600 return 1;
601 #endif
604 /***********************************************************************
605 * wine_rewrite_s4tos2
607 * Convert 4 byte Unicode strings to 2 byte Unicode strings in-place.
608 * This is only practical if literal strings are writable.
610 unsigned short* wine_rewrite_s4tos2(const wchar_t* str4 )
612 unsigned short *str2,*s2;
614 if (str4==NULL)
615 return NULL;
617 if ((*str4 & 0xffff0000) != 0) {
618 /* This string has already been converted. Return it as is */
619 return (unsigned short*)str4;
622 /* Note that we can also end up here if the string has a single
623 * character. In such a case we will convert the string over and
624 * over again. But this is harmless.
626 str2=s2=(unsigned short*)str4;
627 do {
628 *s2=(unsigned short)*str4;
629 s2++;
630 } while (*str4++ != L'\0');
632 return str2;
635 #ifndef HAVE_ECVT
637 * NetBSD 1.5 doesn't have ecvt, fcvt, gcvt. We just check for ecvt, though.
638 * Fix/verify these implementations !
641 /***********************************************************************
642 * ecvt
644 char *ecvt (double number, int ndigits, int *decpt, int *sign)
646 static char buf[40]; /* ought to be enough */
647 char *dec;
648 sprintf(buf, "%.*e", ndigits /* FIXME wrong */, number);
649 *sign = (number < 0);
650 dec = strchr(buf, '.');
651 *decpt = (dec) ? (int)dec - (int)buf : -1;
652 return buf;
655 /***********************************************************************
656 * fcvt
658 char *fcvt (double number, int ndigits, int *decpt, int *sign)
660 static char buf[40]; /* ought to be enough */
661 char *dec;
662 sprintf(buf, "%.*e", ndigits, number);
663 *sign = (number < 0);
664 dec = strchr(buf, '.');
665 *decpt = (dec) ? (int)dec - (int)buf : -1;
666 return buf;
669 /***********************************************************************
670 * gcvt
672 * FIXME: uses both E and F.
674 char *gcvt (double number, size_t ndigit, char *buff)
676 sprintf(buff, "%.*E", (int)ndigit, number);
677 return buff;
679 #endif /* HAVE_ECVT */
682 /***********************************************************************
683 * interlocked functions
685 #ifdef __i386__
687 __ASM_GLOBAL_FUNC(interlocked_cmpxchg,
688 "movl 12(%esp),%eax\n\t"
689 "movl 8(%esp),%ecx\n\t"
690 "movl 4(%esp),%edx\n\t"
691 "lock; cmpxchgl %ecx,(%edx)\n\t"
692 "ret");
693 __ASM_GLOBAL_FUNC(interlocked_cmpxchg_ptr,
694 "movl 12(%esp),%eax\n\t"
695 "movl 8(%esp),%ecx\n\t"
696 "movl 4(%esp),%edx\n\t"
697 "lock; cmpxchgl %ecx,(%edx)\n\t"
698 "ret");
699 __ASM_GLOBAL_FUNC(interlocked_xchg,
700 "movl 8(%esp),%eax\n\t"
701 "movl 4(%esp),%edx\n\t"
702 "lock; xchgl %eax,(%edx)\n\t"
703 "ret");
704 __ASM_GLOBAL_FUNC(interlocked_xchg_ptr,
705 "movl 8(%esp),%eax\n\t"
706 "movl 4(%esp),%edx\n\t"
707 "lock; xchgl %eax,(%edx)\n\t"
708 "ret");
709 __ASM_GLOBAL_FUNC(interlocked_xchg_add,
710 "movl 8(%esp),%eax\n\t"
711 "movl 4(%esp),%edx\n\t"
712 "lock; xaddl %eax,(%edx)\n\t"
713 "ret");
715 #elif defined(__sparc__) && defined(__sun__)
718 * As the earlier Sparc processors lack necessary atomic instructions,
719 * I'm simply falling back to the library-provided _lwp_mutex routines
720 * to ensure mutual exclusion in a way appropriate for the current
721 * architecture.
723 * FIXME: If we have the compare-and-swap instruction (Sparc v9 and above)
724 * we could use this to speed up the Interlocked operations ...
726 #include <synch.h>
727 static lwp_mutex_t interlocked_mutex = DEFAULTMUTEX;
729 long interlocked_cmpxchg( long *dest, long xchg, long compare )
731 _lwp_mutex_lock( &interlocked_mutex );
732 if (*dest == compare) *dest = xchg;
733 else compare = *dest;
734 _lwp_mutex_unlock( &interlocked_mutex );
735 return compare;
738 void *interlocked_cmpxchg_ptr( void **dest, void *xchg, void *compare )
740 _lwp_mutex_lock( &interlocked_mutex );
741 if (*dest == compare) *dest = xchg;
742 else compare = *dest;
743 _lwp_mutex_unlock( &interlocked_mutex );
744 return compare;
747 long interlocked_xchg( long *dest, long val )
749 long retv;
750 _lwp_mutex_lock( &interlocked_mutex );
751 retv = *dest;
752 *dest = val;
753 _lwp_mutex_unlock( &interlocked_mutex );
754 return retv;
757 void *interlocked_xchg_ptr( void **dest, void *val )
759 long retv;
760 _lwp_mutex_lock( &interlocked_mutex );
761 retv = *dest;
762 *dest = val;
763 _lwp_mutex_unlock( &interlocked_mutex );
764 return retv;
767 long interlocked_xchg_add( long *dest, long incr )
769 long retv;
770 _lwp_mutex_lock( &interlocked_mutex );
771 retv = *dest;
772 *dest += incr;
773 _lwp_mutex_unlock( &interlocked_mutex );
774 return retv;
777 #else
778 # error You must implement the interlocked* functions for your CPU
779 #endif