2 * Misc. functions for systems that don't have them
4 * Copyright 1996 Alexandre Julliard
11 #include <be/kernel/fs_info.h>
12 #include <be/kernel/OS.h>
21 #include <sys/types.h>
24 #include <sys/ioctl.h>
28 #ifdef HAVE_SYS_MMAN_H
41 /***********************************************************************
45 unsigned int usleep (unsigned int useconds
)
50 #elif defined(__BEOS__)
51 return snooze(useconds
);
52 #elif defined(HAVE_SELECT)
55 delay
.tv_sec
= useconds
/ 1000000;
56 delay
.tv_usec
= useconds
% 1000000;
58 select( 0, 0, 0, 0, &delay
);
60 #else /* defined(__EMX__) || defined(__BEOS__) || defined(HAVE_SELECT) */
63 #endif /* defined(__EMX__) || defined(__BEOS__) || defined(HAVE_SELECT) */
65 #endif /* HAVE_USLEEP */
67 /***********************************************************************
71 void *memmove( void *dest
, const void *src
, unsigned int len
)
73 register char *dst
= dest
;
75 /* Use memcpy if not overlapping */
76 if ((dst
+ len
<= (char *)src
) || ((char *)src
+ len
<= dst
))
78 memcpy( dst
, src
, len
);
80 /* Otherwise do it the hard way (FIXME: could do better than this) */
83 while (len
--) *dst
++ = *((char *)src
)++;
88 src
= (char *)src
+ len
- 1;
89 while (len
--) *dst
-- = *((char *)src
)--;
93 #endif /* HAVE_MEMMOVE */
95 /***********************************************************************
99 const char *strerror( int err
)
101 /* Let's hope we have sys_errlist then */
102 return sys_errlist
[err
];
104 #endif /* HAVE_STRERROR */
107 /***********************************************************************
110 #ifndef HAVE_GETPAGESIZE
111 size_t getpagesize(void)
114 return sysconf(_SC_PAGESIZE
);
116 # error Cannot get the page size on this platform
119 #endif /* HAVE_GETPAGESIZE */
122 /***********************************************************************
125 #if !defined(HAVE_CLONE) && defined(__linux__)
126 int clone( int (*fn
)(void *), void *stack
, int flags
, void *arg
)
130 void **stack_ptr
= (void **)stack
;
131 *--stack_ptr
= arg
; /* Push argument on stack */
132 *--stack_ptr
= fn
; /* Push function pointer (popped into ebx) */
133 __asm__
__volatile__( "pushl %%ebx\n\t"
136 "popl %%ebx\n\t" /* Contains fn in the child */
137 "testl %%eax,%%eax\n\t"
139 "xorl %ebp,%ebp\n\t" /* Terminate the stack frames */
140 "call *%%ebx\n\t" /* Should never return */
141 "xorl %%eax,%%eax\n\t" /* Just in case it does*/
144 : "0" (SYS_clone
), "r" (flags
), "c" (stack_ptr
) );
145 assert( ret
); /* If ret is 0, we returned from the child function */
146 if (ret
> 0) return ret
;
152 #endif /* __i386__ */
154 #endif /* !HAVE_CLONE && __linux__ */
156 /***********************************************************************
159 #ifndef HAVE_STRCASECMP
160 int strcasecmp( const char *str1
, const char *str2
)
162 const unsigned char *ustr1
= (const unsigned char *)str1
;
163 const unsigned char *ustr2
= (const unsigned char *)str2
;
165 while (*ustr1
&& toupper(*ustr1
) == toupper(*ustr2
)) {
169 return toupper(*ustr1
) - toupper(*ustr2
);
171 #endif /* HAVE_STRCASECMP */
173 /***********************************************************************
176 #ifndef HAVE_STRNCASECMP
177 int strncasecmp( const char *str1
, const char *str2
, size_t n
)
179 const unsigned char *ustr1
= (const unsigned char *)str1
;
180 const unsigned char *ustr2
= (const unsigned char *)str2
;
184 while ((--n
> 0) && *ustr1
) {
185 if ((res
= toupper(*ustr1
) - toupper(*ustr2
))) return res
;
189 return toupper(*ustr1
) - toupper(*ustr2
);
191 #endif /* HAVE_STRNCASECMP */
193 /***********************************************************************
196 * It looks like the openpty that comes with glibc in RedHat 5.0
197 * is buggy (second call returns what looks like a dup of 0 and 1
198 * instead of a new pty), this is a generic replacement.
201 * We should have a autoconf check for this.
204 int openpty(int *master
, int *slave
, char *name
, struct termios
*term
, struct winsize
*winsize
)
206 const char *ptr1
, *ptr2
;
209 strcpy (pts_name
, "/dev/ptyXY");
211 for (ptr1
= "pqrstuvwxyzPQRST"; *ptr1
!= 0; ptr1
++) {
213 for (ptr2
= "0123456789abcdef"; *ptr2
!= 0; ptr2
++) {
216 if ((*master
= open(pts_name
, O_RDWR
)) < 0) {
223 if ((*slave
= open(pts_name
, O_RDWR
)) < 0) {
230 tcsetattr(*slave
, TCSANOW
, term
);
232 ioctl(*slave
, TIOCSWINSZ
, winsize
);
234 strcpy(name
, pts_name
);
241 #endif /* HAVE_OPENPTY */
243 /***********************************************************************
246 #ifndef HAVE_GETNETBYADDR
247 struct netent
*getnetbyaddr(unsigned long net
, int type
)
252 #endif /* defined(HAVE_GETNETBYNAME) */
254 /***********************************************************************
257 #ifndef HAVE_GETNETBYNAME
258 struct netent
*getnetbyname(const char *name
)
263 #endif /* defined(HAVE_GETNETBYNAME) */
265 /***********************************************************************
268 #ifndef HAVE_GETPROTOBYNAME
269 struct protoent
*getprotobyname(const char *name
)
274 #endif /* !defined(HAVE_GETPROTOBYNAME) */
276 /***********************************************************************
279 #ifndef HAVE_GETPROTOBYNUMBER
280 struct protoent
*getprotobynumber(int proto
)
285 #endif /* !defined(HAVE_GETPROTOBYNUMBER) */
287 /***********************************************************************
290 #ifndef HAVE_GETSERVBYPORT
291 struct servent
*getservbyport(int port
, const char *proto
)
296 #endif /* !defined(HAVE_GETSERVBYPORT) */
298 /***********************************************************************
301 #ifndef HAVE_GETSOCKOPT
302 int getsockopt(int socket
, int level
, int option_name
,
303 void *option_value
, size_t *option_len
)
308 #endif /* !defined(HAVE_GETSOCKOPT) */
310 /***********************************************************************
313 #ifndef HAVE_INET_NETWORK
314 unsigned long inet_network(const char *cp
)
319 #endif /* defined(HAVE_INET_NETWORK) */
321 /***********************************************************************
324 #ifndef HAVE_SETTIMEOFDAY
325 int settimeofday(struct timeval
*tp
, void *reserved
)
333 #endif /* HAVE_SETTIMEOFDAY */
335 /***********************************************************************
339 int statfs(const char *name
, struct statfs
*info
)
350 if ((mydev
= dev_for_path(name
)) < 0) {
355 if (fs_stat_dev(mydev
,&fsinfo
) < 0) {
360 info
->f_bsize
= fsinfo
.block_size
;
361 info
->f_blocks
= fsinfo
.total_blocks
;
362 info
->f_bfree
= fsinfo
.free_blocks
;
364 #else /* defined(__BEOS__) */
367 #endif /* defined(__BEOS__) */
369 #endif /* !defined(HAVE_STATFS) */
372 /***********************************************************************
376 int lstat(const char *file_name
, struct stat
*buf
)
378 return stat( file_name
, buf
);
380 #endif /* HAVE_LSTAT */
383 /***********************************************************************
386 * FIXME: this is not thread-safe
389 ssize_t
pread( int fd
, void *buf
, size_t count
, off_t offset
)
394 if ((old_pos
= lseek( fd
, 0, SEEK_CUR
)) == -1) return -1;
395 if (lseek( fd
, offset
, SEEK_SET
) == -1) return -1;
396 if ((ret
= read( fd
, buf
, count
)) == -1)
398 int err
= errno
; /* save errno */
399 lseek( fd
, old_pos
, SEEK_SET
);
403 if (lseek( fd
, old_pos
, SEEK_SET
) == -1) return -1;
406 #endif /* HAVE_PREAD */
409 /***********************************************************************
412 * FIXME: this is not thread-safe
415 ssize_t
pwrite( int fd
, const void *buf
, size_t count
, off_t offset
)
420 if ((old_pos
= lseek( fd
, 0, SEEK_CUR
)) == -1) return -1;
421 if (lseek( fd
, offset
, SEEK_SET
) == -1) return -1;
422 if ((ret
= write( fd
, buf
, count
)) == -1)
424 int err
= errno
; /* save errno */
425 lseek( fd
, old_pos
, SEEK_SET
);
429 if (lseek( fd
, old_pos
, SEEK_SET
) == -1) return -1;
432 #endif /* HAVE_PWRITE */
435 /***********************************************************************
438 #ifndef HAVE_GETRLIMIT
439 int getrlimit (int resource
, struct rlimit
*rlim
)
441 return -1; /* FAIL */
443 #endif /* HAVE_GETRLIMIT */
446 #if defined(__svr4__) || defined(__NetBSD__)
447 /***********************************************************************
450 * The purpose of this routine is to emulate the behaviour of
451 * the Linux mmap() routine if a non-NULL address is passed,
452 * but the MAP_FIXED flag is not set. Linux in this case tries
453 * to place the mapping at the specified address, *unless* the
454 * range is already in use. Solaris, however, completely ignores
455 * the address argument in this case.
457 * As Wine code occasionally relies on the Linux behaviour, e.g. to
458 * be able to map non-relocateable PE executables to their proper
459 * start addresses, or to map the DOS memory to 0, this routine
460 * emulates the Linux behaviour by checking whether the desired
461 * address range is still available, and placing the mapping there
462 * using MAP_FIXED if so.
464 static int try_mmap_fixed (void *addr
, size_t len
, int prot
, int flags
,
465 int fildes
, off_t off
)
467 char * volatile result
= NULL
;
468 int pagesize
= getpagesize();
471 /* We only try to map to a fixed address if
472 addr is non-NULL and properly aligned,
473 and MAP_FIXED isn't already specified. */
477 if ( (uintptr_t)addr
& (pagesize
-1) )
479 if ( flags
& MAP_FIXED
)
482 /* We use vfork() to freeze all threads of the
483 current process. This allows us to check without
484 race condition whether the desired memory range is
485 already in use. Note that because vfork() shares
486 the address spaces between parent and child, we
487 can actually perform the mapping in the child. */
489 if ( (pid
= vfork()) == -1 )
491 perror("try_mmap_fixed: vfork");
499 /* We call mincore() for every page in the desired range.
500 If any of these calls succeeds, the page is already
501 mapped and we must fail. */
502 for ( i
= 0; i
< len
; i
+= pagesize
)
503 if ( mincore( (caddr_t
)addr
+ i
, pagesize
, &vec
) != -1 )
506 /* Perform the mapping with MAP_FIXED set. This is safe
507 now, as none of the pages is currently in use. */
508 result
= mmap( addr
, len
, prot
, flags
| MAP_FIXED
, fildes
, off
);
509 if ( result
== addr
)
512 if ( result
!= (void *) -1 ) /* This should never happen ... */
513 munmap( result
, len
);
518 /* vfork() lets the parent continue only after the child
519 has exited. Furthermore, Wine sets SIGCHLD to SIG_IGN,
520 so we don't need to wait for the child. */
522 return result
== addr
;
526 /***********************************************************************
529 * Portable wrapper for anonymous mmaps
531 void *wine_anon_mmap( void *start
, size_t size
, int prot
, int flags
)
533 static int fdzero
= -1;
540 if ((fdzero
= open( "/dev/zero", O_RDONLY
)) == -1)
542 perror( "/dev/zero: open" );
546 #endif /* MAP_ANON */
549 flags
&= ~MAP_SHARED
;
552 /* Linux EINVAL's on us if we don't pass MAP_PRIVATE to an anon mmap */
554 flags
|= MAP_PRIVATE
;
557 #if defined(__svr4__) || defined(__NetBSD__)
558 if ( try_mmap_fixed( start
, size
, prot
, flags
, fdzero
, 0 ) )
562 return mmap( start
, size
, prot
, flags
, fdzero
, 0 );
567 * These functions provide wrappers around dlopen() and associated
568 * functions. They work around a bug in glibc 2.1.x where calling
569 * a dl*() function after a previous dl*() function has failed
570 * without a dlerror() call between the two will cause a crash.
571 * They all take a pointer to a buffer that
572 * will receive the error description (from dlerror()). This
573 * parameter may be NULL if the error description is not required.
576 /***********************************************************************
579 void *wine_dlopen( const char *filename
, int flag
, char *error
, int errorsize
)
584 dlerror(); dlerror();
585 ret
= dlopen( filename
, flag
);
589 strncpy( error
, s
? s
: "", errorsize
);
590 error
[errorsize
- 1] = '\0';
597 strncpy( error
, "dlopen interface not detected by configure", errorsize
);
598 error
[errorsize
- 1] = '\0';
604 /***********************************************************************
607 void *wine_dlsym( void *handle
, const char *symbol
, char *error
, int errorsize
)
612 dlerror(); dlerror();
613 ret
= dlsym( handle
, symbol
);
617 strncpy( error
, s
? s
: "", errorsize
);
618 error
[errorsize
- 1] = '\0';
625 strncpy( error
, "dlopen interface not detected by configure", errorsize
);
626 error
[errorsize
- 1] = '\0';
632 /***********************************************************************
635 int wine_dlclose( void *handle
, char *error
, int errorsize
)
640 dlerror(); dlerror();
641 ret
= dlclose( handle
);
645 strncpy( error
, s
? s
: "", errorsize
);
646 error
[errorsize
- 1] = '\0';
653 strncpy( error
, "dlopen interface not detected by configure", errorsize
);
654 error
[errorsize
- 1] = '\0';
660 /***********************************************************************
661 * wine_rewrite_s4tos2
663 * Convert 4 byte Unicode strings to 2 byte Unicode strings in-place.
664 * This is only practical if literal strings are writable.
666 unsigned short* wine_rewrite_s4tos2(const wchar_t* str4
)
668 unsigned short *str2
,*s2
;
673 if ((*str4
& 0xffff0000) != 0) {
674 /* This string has already been converted. Return it as is */
675 return (unsigned short*)str4
;
678 /* Note that we can also end up here if the string has a single
679 * character. In such a case we will convert the string over and
680 * over again. But this is harmless.
682 str2
=s2
=(unsigned short*)str4
;
684 *s2
=(unsigned short)*str4
;
686 } while (*str4
++ != L
'\0');
693 * NetBSD 1.5 doesn't have ecvt, fcvt, gcvt. We just check for ecvt, though.
694 * Fix/verify these implementations !
697 /***********************************************************************
700 char *ecvt (double number
, int ndigits
, int *decpt
, int *sign
)
702 static char buf
[40]; /* ought to be enough */
704 sprintf(buf
, "%.*e", ndigits
/* FIXME wrong */, number
);
705 *sign
= (number
< 0);
706 dec
= strchr(buf
, '.');
707 *decpt
= (dec
) ? (int)dec
- (int)buf
: -1;
711 /***********************************************************************
714 char *fcvt (double number
, int ndigits
, int *decpt
, int *sign
)
716 static char buf
[40]; /* ought to be enough */
718 sprintf(buf
, "%.*e", ndigits
, number
);
719 *sign
= (number
< 0);
720 dec
= strchr(buf
, '.');
721 *decpt
= (dec
) ? (int)dec
- (int)buf
: -1;
725 /***********************************************************************
728 * FIXME: uses both E and F.
730 char *gcvt (double number
, size_t ndigit
, char *buff
)
732 sprintf(buff
, "%.*E", (int)ndigit
, number
);
735 #endif /* HAVE_ECVT */