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_TIME_h
37 # include <sys/time.h>
40 #include <sys/ioctl.h>
44 #ifdef HAVE_SYS_MMAN_H
57 /***********************************************************************
61 unsigned int usleep (unsigned int useconds)
66 #elif defined(__BEOS__)
67 return snooze(useconds);
68 #elif defined(HAVE_SELECT)
71 delay.tv_sec = useconds / 1000000;
72 delay.tv_usec = useconds % 1000000;
74 select( 0, 0, 0, 0, &delay );
76 #else /* defined(__EMX__) || defined(__BEOS__) || defined(HAVE_SELECT) */
79 #endif /* defined(__EMX__) || defined(__BEOS__) || defined(HAVE_SELECT) */
81 #endif /* HAVE_USLEEP */
83 /***********************************************************************
87 void *memmove( void *dest, const void *src, unsigned int len )
89 register char *dst = dest;
91 /* Use memcpy if not overlapping */
92 if ((dst + len <= (char *)src) || ((char *)src + len <= dst))
94 memcpy( dst, src, len );
96 /* Otherwise do it the hard way (FIXME: could do better than this) */
99 while (len--) *dst++ = *((char *)src)++;
104 src = (char *)src + len - 1;
105 while (len--) *dst-- = *((char *)src)--;
109 #endif /* HAVE_MEMMOVE */
111 /***********************************************************************
114 #ifndef HAVE_STRERROR
115 const char *strerror( int err )
117 /* Let's hope we have sys_errlist then */
118 return sys_errlist[err];
120 #endif /* HAVE_STRERROR */
123 /***********************************************************************
126 #ifndef HAVE_GETPAGESIZE
127 size_t getpagesize(void)
130 return sysconf(_SC_PAGESIZE);
132 # error Cannot get the page size on this platform
135 #endif /* HAVE_GETPAGESIZE */
138 /***********************************************************************
141 #if !defined(HAVE_CLONE) && defined(__linux__)
142 int clone( int (*fn)(void *), void *stack, int flags, void *arg )
146 void **stack_ptr = (void **)stack;
147 *--stack_ptr = arg; /* Push argument on stack */
148 *--stack_ptr = fn; /* Push function pointer (popped into ebx) */
149 __asm__ __volatile__( "pushl %%ebx\n\t"
152 "popl %%ebx\n\t" /* Contains fn in the child */
153 "testl %%eax,%%eax\n\t"
155 "xorl %ebp,%ebp\n\t" /* Terminate the stack frames */
156 "call *%%ebx\n\t" /* Should never return */
157 "xorl %%eax,%%eax\n\t" /* Just in case it does*/
160 : "0" (SYS_clone), "r" (flags), "c" (stack_ptr) );
161 assert( ret ); /* If ret is 0, we returned from the child function */
162 if (ret > 0) return ret;
168 #endif /* __i386__ */
170 #endif /* !HAVE_CLONE && __linux__ */
172 /***********************************************************************
175 #ifndef HAVE_STRCASECMP
176 int strcasecmp( const char *str1, const char *str2 )
178 const unsigned char *ustr1 = (const unsigned char *)str1;
179 const unsigned char *ustr2 = (const unsigned char *)str2;
181 while (*ustr1 && toupper(*ustr1) == toupper(*ustr2)) {
185 return toupper(*ustr1) - toupper(*ustr2);
187 #endif /* HAVE_STRCASECMP */
189 /***********************************************************************
192 #ifndef HAVE_STRNCASECMP
193 int strncasecmp( const char *str1, const char *str2, size_t n )
195 const unsigned char *ustr1 = (const unsigned char *)str1;
196 const unsigned char *ustr2 = (const unsigned char *)str2;
200 while ((--n > 0) && *ustr1) {
201 if ((res = toupper(*ustr1) - toupper(*ustr2))) return res;
205 return toupper(*ustr1) - toupper(*ustr2);
207 #endif /* HAVE_STRNCASECMP */
209 /***********************************************************************
212 * It looks like the openpty that comes with glibc in RedHat 5.0
213 * is buggy (second call returns what looks like a dup of 0 and 1
214 * instead of a new pty), this is a generic replacement.
217 * We should have a autoconf check for this.
220 int openpty(int *master, int *slave, char *name, struct termios *term, struct winsize *winsize)
222 const char *ptr1, *ptr2;
225 strcpy (pts_name, "/dev/ptyXY");
227 for (ptr1 = "pqrstuvwxyzPQRST"; *ptr1 != 0; ptr1++) {
229 for (ptr2 = "0123456789abcdef"; *ptr2 != 0; ptr2++) {
232 if ((*master = open(pts_name, O_RDWR)) < 0) {
239 if ((*slave = open(pts_name, O_RDWR)) < 0) {
246 tcsetattr(*slave, TCSANOW, term);
248 ioctl(*slave, TIOCSWINSZ, winsize);
250 strcpy(name, pts_name);
257 #endif /* HAVE_OPENPTY */
259 /***********************************************************************
262 #ifndef HAVE_GETNETBYADDR
263 struct netent *getnetbyaddr(unsigned long net, int type)
268 #endif /* defined(HAVE_GETNETBYNAME) */
270 /***********************************************************************
273 #ifndef HAVE_GETNETBYNAME
274 struct netent *getnetbyname(const char *name)
279 #endif /* defined(HAVE_GETNETBYNAME) */
281 /***********************************************************************
284 #ifndef HAVE_GETPROTOBYNAME
285 struct protoent *getprotobyname(const char *name)
290 #endif /* !defined(HAVE_GETPROTOBYNAME) */
292 /***********************************************************************
295 #ifndef HAVE_GETPROTOBYNUMBER
296 struct protoent *getprotobynumber(int proto)
301 #endif /* !defined(HAVE_GETPROTOBYNUMBER) */
303 /***********************************************************************
306 #ifndef HAVE_GETSERVBYPORT
307 struct servent *getservbyport(int port, const char *proto)
312 #endif /* !defined(HAVE_GETSERVBYPORT) */
314 /***********************************************************************
317 #ifndef HAVE_GETSOCKOPT
318 int getsockopt(int socket, int level, int option_name,
319 void *option_value, size_t *option_len)
324 #endif /* !defined(HAVE_GETSOCKOPT) */
326 /***********************************************************************
329 #ifndef HAVE_INET_NETWORK
330 unsigned long inet_network(const char *cp)
335 #endif /* defined(HAVE_INET_NETWORK) */
337 /***********************************************************************
341 int statfs(const char *name, struct statfs *info)
352 if ((mydev = dev_for_path(name)) < 0) {
357 if (fs_stat_dev(mydev,&fsinfo) < 0) {
362 info->f_bsize = fsinfo.block_size;
363 info->f_blocks = fsinfo.total_blocks;
364 info->f_bfree = fsinfo.free_blocks;
366 #else /* defined(__BEOS__) */
369 #endif /* defined(__BEOS__) */
371 #endif /* !defined(HAVE_STATFS) */
374 /***********************************************************************
378 int lstat(const char *file_name, struct stat *buf)
380 return stat( file_name, buf );
382 #endif /* HAVE_LSTAT */
385 /***********************************************************************
388 * FIXME: this is not thread-safe
391 ssize_t pread( int fd, void *buf, size_t count, off_t offset )
396 if ((old_pos = lseek( fd, 0, SEEK_CUR )) == -1) return -1;
397 if (lseek( fd, offset, SEEK_SET ) == -1) return -1;
398 if ((ret = read( fd, buf, count )) == -1)
400 int err = errno; /* save errno */
401 lseek( fd, old_pos, SEEK_SET );
405 if (lseek( fd, old_pos, SEEK_SET ) == -1) return -1;
408 #endif /* HAVE_PREAD */
411 /***********************************************************************
414 * FIXME: this is not thread-safe
417 ssize_t pwrite( int fd, const void *buf, size_t count, off_t offset )
422 if ((old_pos = lseek( fd, 0, SEEK_CUR )) == -1) return -1;
423 if (lseek( fd, offset, SEEK_SET ) == -1) return -1;
424 if ((ret = write( fd, buf, count )) == -1)
426 int err = errno; /* save errno */
427 lseek( fd, old_pos, SEEK_SET );
431 if (lseek( fd, old_pos, SEEK_SET ) == -1) return -1;
434 #endif /* HAVE_PWRITE */
437 /***********************************************************************
440 #ifndef HAVE_GETRLIMIT
441 int getrlimit (int resource, struct rlimit *rlim)
443 return -1; /* FAIL */
445 #endif /* HAVE_GETRLIMIT */
448 #if defined(__svr4__) || defined(__NetBSD__)
449 /***********************************************************************
452 * The purpose of this routine is to emulate the behaviour of
453 * the Linux mmap() routine if a non-NULL address is passed,
454 * but the MAP_FIXED flag is not set. Linux in this case tries
455 * to place the mapping at the specified address, *unless* the
456 * range is already in use. Solaris, however, completely ignores
457 * the address argument in this case.
459 * As Wine code occasionally relies on the Linux behaviour, e.g. to
460 * be able to map non-relocateable PE executables to their proper
461 * start addresses, or to map the DOS memory to 0, this routine
462 * emulates the Linux behaviour by checking whether the desired
463 * address range is still available, and placing the mapping there
464 * using MAP_FIXED if so.
466 static int try_mmap_fixed (void *addr, size_t len, int prot, int flags,
467 int fildes, off_t off)
469 char * volatile result = NULL;
470 int pagesize = getpagesize();
473 /* We only try to map to a fixed address if
474 addr is non-NULL and properly aligned,
475 and MAP_FIXED isn't already specified. */
479 if ( (uintptr_t)addr & (pagesize-1) )
481 if ( flags & MAP_FIXED )
484 /* We use vfork() to freeze all threads of the
485 current process. This allows us to check without
486 race condition whether the desired memory range is
487 already in use. Note that because vfork() shares
488 the address spaces between parent and child, we
489 can actually perform the mapping in the child. */
491 if ( (pid = vfork()) == -1 )
493 perror("try_mmap_fixed: vfork");
501 /* We call mincore() for every page in the desired range.
502 If any of these calls succeeds, the page is already
503 mapped and we must fail. */
504 for ( i = 0; i < len; i += pagesize )
505 if ( mincore( (caddr_t)addr + i, pagesize, &vec ) != -1 )
508 /* Perform the mapping with MAP_FIXED set. This is safe
509 now, as none of the pages is currently in use. */
510 result = mmap( addr, len, prot, flags | MAP_FIXED, fildes, off );
511 if ( result == addr )
514 if ( result != (void *) -1 ) /* This should never happen ... */
515 munmap( result, len );
520 /* vfork() lets the parent continue only after the child
521 has exited. Furthermore, Wine sets SIGCHLD to SIG_IGN,
522 so we don't need to wait for the child. */
524 return result == addr;
528 /***********************************************************************
531 * Portable wrapper for anonymous mmaps
533 void *wine_anon_mmap( void *start, size_t size, int prot, int flags )
535 static int fdzero = -1;
542 if ((fdzero = open( "/dev/zero", O_RDONLY )) == -1)
544 perror( "/dev/zero: open" );
548 #endif /* MAP_ANON */
551 flags &= ~MAP_SHARED;
554 /* Linux EINVAL's on us if we don't pass MAP_PRIVATE to an anon mmap */
556 flags |= MAP_PRIVATE;
559 #if defined(__svr4__) || defined(__NetBSD__)
560 if ( try_mmap_fixed( start, size, prot, flags, fdzero, 0 ) )
564 return mmap( start, size, prot, flags, fdzero, 0 );
569 * These functions provide wrappers around dlopen() and associated
570 * functions. They work around a bug in glibc 2.1.x where calling
571 * a dl*() function after a previous dl*() function has failed
572 * without a dlerror() call between the two will cause a crash.
573 * They all take a pointer to a buffer that
574 * will receive the error description (from dlerror()). This
575 * parameter may be NULL if the error description is not required.
578 /***********************************************************************
581 void *wine_dlopen( const char *filename, int flag, char *error, int errorsize )
586 dlerror(); dlerror();
587 ret = dlopen( filename, flag );
591 strncpy( error, s ? s : "", errorsize );
592 error[errorsize - 1] = '\0';
599 strncpy( error, "dlopen interface not detected by configure", errorsize );
600 error[errorsize - 1] = '\0';
606 /***********************************************************************
609 void *wine_dlsym( void *handle, const char *symbol, char *error, int errorsize )
614 dlerror(); dlerror();
615 ret = dlsym( handle, symbol );
619 strncpy( error, s ? s : "", errorsize );
620 error[errorsize - 1] = '\0';
627 strncpy( error, "dlopen interface not detected by configure", errorsize );
628 error[errorsize - 1] = '\0';
634 /***********************************************************************
637 int wine_dlclose( void *handle, char *error, int errorsize )
642 dlerror(); dlerror();
643 ret = dlclose( handle );
647 strncpy( error, s ? s : "", errorsize );
648 error[errorsize - 1] = '\0';
655 strncpy( error, "dlopen interface not detected by configure", errorsize );
656 error[errorsize - 1] = '\0';
662 /***********************************************************************
663 * wine_rewrite_s4tos2
665 * Convert 4 byte Unicode strings to 2 byte Unicode strings in-place.
666 * This is only practical if literal strings are writable.
668 unsigned short* wine_rewrite_s4tos2(const wchar_t* str4 )
670 unsigned short *str2,*s2;
675 if ((*str4 & 0xffff0000) != 0) {
676 /* This string has already been converted. Return it as is */
677 return (unsigned short*)str4;
680 /* Note that we can also end up here if the string has a single
681 * character. In such a case we will convert the string over and
682 * over again. But this is harmless.
684 str2=s2=(unsigned short*)str4;
686 *s2=(unsigned short)*str4;
688 } while (*str4++ != L'\0');
695 * NetBSD 1.5 doesn't have ecvt, fcvt, gcvt. We just check for ecvt, though.
696 * Fix/verify these implementations !
699 /***********************************************************************
702 char *ecvt (double number, int ndigits, int *decpt, int *sign)
704 static char buf[40]; /* ought to be enough */
706 sprintf(buf, "%.*e", ndigits /* FIXME wrong */, number);
707 *sign = (number < 0);
708 dec = strchr(buf, '.');
709 *decpt = (dec) ? (int)dec - (int)buf : -1;
713 /***********************************************************************
716 char *fcvt (double number, int ndigits, int *decpt, int *sign)
718 static char buf[40]; /* ought to be enough */
720 sprintf(buf, "%.*e", ndigits, number);
721 *sign = (number < 0);
722 dec = strchr(buf, '.');
723 *decpt = (dec) ? (int)dec - (int)buf : -1;
727 /***********************************************************************
730 * FIXME: uses both E and F.
732 char *gcvt (double number, size_t ndigit, char *buff)
734 sprintf(buff, "%.*E", (int)ndigit, number);
737 #endif /* HAVE_ECVT */