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
22 #include "wine/port.h"
25 #include <be/kernel/fs_info.h>
26 #include <be/kernel/OS.h>
35 #include <sys/types.h>
36 #ifdef HAVE_SYS_INTTYPES_H
37 # include <sys/inttypes.h>
39 #ifdef HAVE_SYS_TIME_h
40 # include <sys/time.h>
43 #include <sys/ioctl.h>
47 #ifdef HAVE_SYS_MMAN_H
60 /***********************************************************************
64 unsigned int usleep (unsigned int useconds)
69 #elif defined(__BEOS__)
70 return snooze(useconds);
71 #elif defined(HAVE_SELECT)
74 delay.tv_sec = useconds / 1000000;
75 delay.tv_usec = useconds % 1000000;
77 select( 0, 0, 0, 0, &delay );
79 #else /* defined(__EMX__) || defined(__BEOS__) || defined(HAVE_SELECT) */
82 #endif /* defined(__EMX__) || defined(__BEOS__) || defined(HAVE_SELECT) */
84 #endif /* HAVE_USLEEP */
86 /***********************************************************************
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) */
102 while (len--) *dst++ = *((char *)src)++;
107 src = (char *)src + len - 1;
108 while (len--) *dst-- = *((char *)src)--;
112 #endif /* HAVE_MEMMOVE */
114 /***********************************************************************
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 /***********************************************************************
129 #ifndef HAVE_GETPAGESIZE
130 size_t getpagesize(void)
133 return sysconf(_SC_PAGESIZE);
135 # error Cannot get the page size on this platform
138 #endif /* HAVE_GETPAGESIZE */
141 /***********************************************************************
144 #if !defined(HAVE_CLONE) && defined(__linux__)
145 int clone( int (*fn)(void *), void *stack, int flags, void *arg )
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"
155 "popl %%ebx\n\t" /* Contains fn in the child */
156 "testl %%eax,%%eax\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*/
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;
171 #endif /* __i386__ */
173 #endif /* !HAVE_CLONE && __linux__ */
175 /***********************************************************************
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)) {
188 return toupper(*ustr1) - toupper(*ustr2);
190 #endif /* HAVE_STRCASECMP */
192 /***********************************************************************
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;
203 while ((--n > 0) && *ustr1) {
204 if ((res = toupper(*ustr1) - toupper(*ustr2))) return res;
208 return toupper(*ustr1) - toupper(*ustr2);
210 #endif /* HAVE_STRNCASECMP */
212 /***********************************************************************
215 * It looks like the openpty that comes with glibc in RedHat 5.0
216 * is buggy (second call returns what looks like a dup of 0 and 1
217 * instead of a new pty), this is a generic replacement.
220 * We should have a autoconf check for this.
223 int openpty(int *master, int *slave, char *name, struct termios *term, struct winsize *winsize)
225 const char *ptr1, *ptr2;
228 strcpy (pts_name, "/dev/ptyXY");
230 for (ptr1 = "pqrstuvwxyzPQRST"; *ptr1 != 0; ptr1++) {
232 for (ptr2 = "0123456789abcdef"; *ptr2 != 0; ptr2++) {
235 if ((*master = open(pts_name, O_RDWR)) < 0) {
242 if ((*slave = open(pts_name, O_RDWR)) < 0) {
249 tcsetattr(*slave, TCSANOW, term);
251 ioctl(*slave, TIOCSWINSZ, winsize);
253 strcpy(name, pts_name);
260 #endif /* HAVE_OPENPTY */
262 /***********************************************************************
265 #ifndef HAVE_GETNETBYADDR
266 struct netent *getnetbyaddr(unsigned long net, int type)
271 #endif /* defined(HAVE_GETNETBYNAME) */
273 /***********************************************************************
276 #ifndef HAVE_GETNETBYNAME
277 struct netent *getnetbyname(const char *name)
282 #endif /* defined(HAVE_GETNETBYNAME) */
284 /***********************************************************************
287 #ifndef HAVE_GETPROTOBYNAME
288 struct protoent *getprotobyname(const char *name)
293 #endif /* !defined(HAVE_GETPROTOBYNAME) */
295 /***********************************************************************
298 #ifndef HAVE_GETPROTOBYNUMBER
299 struct protoent *getprotobynumber(int proto)
304 #endif /* !defined(HAVE_GETPROTOBYNUMBER) */
306 /***********************************************************************
309 #ifndef HAVE_GETSERVBYPORT
310 struct servent *getservbyport(int port, const char *proto)
315 #endif /* !defined(HAVE_GETSERVBYPORT) */
317 /***********************************************************************
320 #ifndef HAVE_GETSOCKOPT
321 int getsockopt(int socket, int level, int option_name,
322 void *option_value, size_t *option_len)
327 #endif /* !defined(HAVE_GETSOCKOPT) */
329 /***********************************************************************
332 #ifndef HAVE_INET_NETWORK
333 unsigned long inet_network(const char *cp)
338 #endif /* defined(HAVE_INET_NETWORK) */
340 /***********************************************************************
344 int statfs(const char *name, struct statfs *info)
355 if ((mydev = dev_for_path(name)) < 0) {
360 if (fs_stat_dev(mydev,&fsinfo) < 0) {
365 info->f_bsize = fsinfo.block_size;
366 info->f_blocks = fsinfo.total_blocks;
367 info->f_bfree = fsinfo.free_blocks;
369 #else /* defined(__BEOS__) */
372 #endif /* defined(__BEOS__) */
374 #endif /* !defined(HAVE_STATFS) */
377 /***********************************************************************
381 int lstat(const char *file_name, struct stat *buf)
383 return stat( file_name, buf );
385 #endif /* HAVE_LSTAT */
388 /***********************************************************************
391 * FIXME: this is not thread-safe
394 ssize_t pread( int fd, void *buf, size_t count, off_t offset )
399 if ((old_pos = lseek( fd, 0, SEEK_CUR )) == -1) return -1;
400 if (lseek( fd, offset, SEEK_SET ) == -1) return -1;
401 if ((ret = read( fd, buf, count )) == -1)
403 int err = errno; /* save errno */
404 lseek( fd, old_pos, SEEK_SET );
408 if (lseek( fd, old_pos, SEEK_SET ) == -1) return -1;
411 #endif /* HAVE_PREAD */
414 /***********************************************************************
417 * FIXME: this is not thread-safe
420 ssize_t pwrite( int fd, const void *buf, size_t count, off_t offset )
425 if ((old_pos = lseek( fd, 0, SEEK_CUR )) == -1) return -1;
426 if (lseek( fd, offset, SEEK_SET ) == -1) return -1;
427 if ((ret = write( fd, buf, count )) == -1)
429 int err = errno; /* save errno */
430 lseek( fd, old_pos, SEEK_SET );
434 if (lseek( fd, old_pos, SEEK_SET ) == -1) return -1;
437 #endif /* HAVE_PWRITE */
440 /***********************************************************************
443 #ifndef HAVE_GETRLIMIT
444 int getrlimit (int resource, struct rlimit *rlim)
446 return -1; /* FAIL */
448 #endif /* HAVE_GETRLIMIT */
451 #if defined(__svr4__) || defined(__NetBSD__)
452 /***********************************************************************
455 * The purpose of this routine is to emulate the behaviour of
456 * the Linux mmap() routine if a non-NULL address is passed,
457 * but the MAP_FIXED flag is not set. Linux in this case tries
458 * to place the mapping at the specified address, *unless* the
459 * range is already in use. Solaris, however, completely ignores
460 * the address argument in this case.
462 * As Wine code occasionally relies on the Linux behaviour, e.g. to
463 * be able to map non-relocateable PE executables to their proper
464 * start addresses, or to map the DOS memory to 0, this routine
465 * emulates the Linux behaviour by checking whether the desired
466 * address range is still available, and placing the mapping there
467 * using MAP_FIXED if so.
469 static int try_mmap_fixed (void *addr, size_t len, int prot, int flags,
470 int fildes, off_t off)
472 char * volatile result = NULL;
473 int pagesize = getpagesize();
476 /* We only try to map to a fixed address if
477 addr is non-NULL and properly aligned,
478 and MAP_FIXED isn't already specified. */
482 if ( (uintptr_t)addr & (pagesize-1) )
484 if ( flags & MAP_FIXED )
487 /* We use vfork() to freeze all threads of the
488 current process. This allows us to check without
489 race condition whether the desired memory range is
490 already in use. Note that because vfork() shares
491 the address spaces between parent and child, we
492 can actually perform the mapping in the child. */
494 if ( (pid = vfork()) == -1 )
496 perror("try_mmap_fixed: vfork");
504 /* We call mincore() for every page in the desired range.
505 If any of these calls succeeds, the page is already
506 mapped and we must fail. */
507 for ( i = 0; i < len; i += pagesize )
508 if ( mincore( (caddr_t)addr + i, pagesize, &vec ) != -1 )
511 /* Perform the mapping with MAP_FIXED set. This is safe
512 now, as none of the pages is currently in use. */
513 result = mmap( addr, len, prot, flags | MAP_FIXED, fildes, off );
514 if ( result == addr )
517 if ( result != (void *) -1 ) /* This should never happen ... */
518 munmap( result, len );
523 /* vfork() lets the parent continue only after the child
524 has exited. Furthermore, Wine sets SIGCHLD to SIG_IGN,
525 so we don't need to wait for the child. */
527 return result == addr;
531 /***********************************************************************
534 * Portable wrapper for anonymous mmaps
536 void *wine_anon_mmap( void *start, size_t size, int prot, int flags )
538 static int fdzero = -1;
545 if ((fdzero = open( "/dev/zero", O_RDONLY )) == -1)
547 perror( "/dev/zero: open" );
551 #endif /* MAP_ANON */
554 flags &= ~MAP_SHARED;
557 /* Linux EINVAL's on us if we don't pass MAP_PRIVATE to an anon mmap */
559 flags |= MAP_PRIVATE;
562 #if defined(__svr4__) || defined(__NetBSD__)
563 if ( try_mmap_fixed( start, size, prot, flags, fdzero, 0 ) )
567 return mmap( start, size, prot, flags, fdzero, 0 );
572 * These functions provide wrappers around dlopen() and associated
573 * functions. They work around a bug in glibc 2.1.x where calling
574 * a dl*() function after a previous dl*() function has failed
575 * without a dlerror() call between the two will cause a crash.
576 * They all take a pointer to a buffer that
577 * will receive the error description (from dlerror()). This
578 * parameter may be NULL if the error description is not required.
581 /***********************************************************************
584 void *wine_dlopen( const char *filename, int flag, char *error, int errorsize )
589 dlerror(); dlerror();
590 ret = dlopen( filename, flag );
594 strncpy( error, s ? s : "", errorsize );
595 error[errorsize - 1] = '\0';
602 strncpy( error, "dlopen interface not detected by configure", errorsize );
603 error[errorsize - 1] = '\0';
609 /***********************************************************************
612 void *wine_dlsym( void *handle, const char *symbol, char *error, int errorsize )
617 dlerror(); dlerror();
618 ret = dlsym( handle, symbol );
622 strncpy( error, s ? s : "", errorsize );
623 error[errorsize - 1] = '\0';
630 strncpy( error, "dlopen interface not detected by configure", errorsize );
631 error[errorsize - 1] = '\0';
637 /***********************************************************************
640 int wine_dlclose( void *handle, char *error, int errorsize )
645 dlerror(); dlerror();
646 ret = dlclose( handle );
650 strncpy( error, s ? s : "", errorsize );
651 error[errorsize - 1] = '\0';
658 strncpy( error, "dlopen interface not detected by configure", errorsize );
659 error[errorsize - 1] = '\0';
665 /***********************************************************************
666 * wine_rewrite_s4tos2
668 * Convert 4 byte Unicode strings to 2 byte Unicode strings in-place.
669 * This is only practical if literal strings are writable.
671 unsigned short* wine_rewrite_s4tos2(const wchar_t* str4 )
673 unsigned short *str2,*s2;
678 if ((*str4 & 0xffff0000) != 0) {
679 /* This string has already been converted. Return it as is */
680 return (unsigned short*)str4;
683 /* Note that we can also end up here if the string has a single
684 * character. In such a case we will convert the string over and
685 * over again. But this is harmless.
687 str2=s2=(unsigned short*)str4;
689 *s2=(unsigned short)*str4;
691 } while (*str4++ != L'\0');
698 * NetBSD 1.5 doesn't have ecvt, fcvt, gcvt. We just check for ecvt, though.
699 * Fix/verify these implementations !
702 /***********************************************************************
705 char *ecvt (double number, int ndigits, int *decpt, int *sign)
707 static char buf[40]; /* ought to be enough */
709 sprintf(buf, "%.*e", ndigits /* FIXME wrong */, number);
710 *sign = (number < 0);
711 dec = strchr(buf, '.');
712 *decpt = (dec) ? (int)dec - (int)buf : -1;
716 /***********************************************************************
719 char *fcvt (double number, int ndigits, int *decpt, int *sign)
721 static char buf[40]; /* ought to be enough */
723 sprintf(buf, "%.*e", ndigits, number);
724 *sign = (number < 0);
725 dec = strchr(buf, '.');
726 *decpt = (dec) ? (int)dec - (int)buf : -1;
730 /***********************************************************************
733 * FIXME: uses both E and F.
735 char *gcvt (double number, size_t ndigit, char *buff)
737 sprintf(buff, "%.*E", (int)ndigit, number);
740 #endif /* HAVE_ECVT */