Changed the GDI driver interface to pass an opaque PHYSDEV pointer
[wine] / library / port.c
1 /*
2  * Misc. functions for systems that don't have them
3  *
4  * Copyright 1996 Alexandre Julliard
5  *
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.
10  *
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.
15  *
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
19  */
20
21 #include "config.h"
22 #include "wine/port.h"
23
24 #ifdef __BEOS__
25 #include <be/kernel/fs_info.h>
26 #include <be/kernel/OS.h>
27 #endif
28
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_TIME_h
37 # include <sys/time.h>
38 #endif
39 #include <sys/stat.h>
40 #include <sys/ioctl.h>
41 #include <errno.h>
42 #include <fcntl.h>
43 #include <termios.h>
44 #ifdef HAVE_SYS_MMAN_H
45 #include <sys/mman.h>
46 #endif
47 #ifdef HAVE_LIBIO_H
48 # include <libio.h>
49 #endif
50 #ifdef HAVE_SYSCALL_H
51 # include <syscall.h>
52 #endif
53 #ifdef HAVE_STDINT_H
54 # include <stdint.h>
55 #endif
56
57 /***********************************************************************
58  *              usleep
59  */
60 #ifndef HAVE_USLEEP
61 unsigned int usleep (unsigned int useconds)
62 {
63 #if defined(__EMX__)
64     DosSleep(useconds);
65     return 0;
66 #elif defined(__BEOS__)
67     return snooze(useconds);
68 #elif defined(HAVE_SELECT)
69     struct timeval delay;
70
71     delay.tv_sec = useconds / 1000000;
72     delay.tv_usec = useconds % 1000000;
73
74     select( 0, 0, 0, 0, &delay );
75     return 0;
76 #else /* defined(__EMX__) || defined(__BEOS__) || defined(HAVE_SELECT) */
77     errno = ENOSYS;
78     return -1;
79 #endif /* defined(__EMX__) || defined(__BEOS__) || defined(HAVE_SELECT) */
80 }
81 #endif /* HAVE_USLEEP */
82
83 /***********************************************************************
84  *              memmove
85  */
86 #ifndef HAVE_MEMMOVE
87 void *memmove( void *dest, const void *src, unsigned int len )
88 {
89     register char *dst = dest;
90
91     /* Use memcpy if not overlapping */
92     if ((dst + len <= (char *)src) || ((char *)src + len <= dst))
93     {
94         memcpy( dst, src, len );
95     }
96     /* Otherwise do it the hard way (FIXME: could do better than this) */
97     else if (dst < src)
98     {
99         while (len--) *dst++ = *((char *)src)++;
100     }
101     else
102     {
103         dst += len - 1;
104         src = (char *)src + len - 1;
105         while (len--) *dst-- = *((char *)src)--;
106     }
107     return dest;
108 }
109 #endif  /* HAVE_MEMMOVE */
110
111 /***********************************************************************
112  *              strerror
113  */
114 #ifndef HAVE_STRERROR
115 const char *strerror( int err )
116 {
117     /* Let's hope we have sys_errlist then */
118     return sys_errlist[err];
119 }
120 #endif  /* HAVE_STRERROR */
121
122
123 /***********************************************************************
124  *              getpagesize
125  */
126 #ifndef HAVE_GETPAGESIZE
127 size_t getpagesize(void)
128 {
129 # ifdef __svr4__
130     return sysconf(_SC_PAGESIZE);
131 # else
132 #  error Cannot get the page size on this platform
133 # endif
134 }
135 #endif  /* HAVE_GETPAGESIZE */
136
137
138 /***********************************************************************
139  *              clone
140  */
141 #if !defined(HAVE_CLONE) && defined(__linux__)
142 int clone( int (*fn)(void *), void *stack, int flags, void *arg )
143 {
144 #ifdef __i386__
145     int ret;
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"
150                           "movl %2,%%ebx\n\t"
151                           "int $0x80\n\t"
152                           "popl %%ebx\n\t"   /* Contains fn in the child */
153                           "testl %%eax,%%eax\n\t"
154                           "jnz 0f\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*/
158                           "0:"
159                           : "=a" (ret)
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;
163     errno = -ret;
164     return -1;
165 #else
166     errno = EINVAL;
167     return -1;
168 #endif  /* __i386__ */
169 }
170 #endif  /* !HAVE_CLONE && __linux__ */
171
172 /***********************************************************************
173  *              strcasecmp
174  */
175 #ifndef HAVE_STRCASECMP
176 int strcasecmp( const char *str1, const char *str2 )
177 {
178     const unsigned char *ustr1 = (const unsigned char *)str1;
179     const unsigned char *ustr2 = (const unsigned char *)str2;
180
181     while (*ustr1 && toupper(*ustr1) == toupper(*ustr2)) {
182         ustr1++;
183         ustr2++;
184     }
185     return toupper(*ustr1) - toupper(*ustr2);
186 }
187 #endif /* HAVE_STRCASECMP */
188
189 /***********************************************************************
190  *              strncasecmp
191  */
192 #ifndef HAVE_STRNCASECMP
193 int strncasecmp( const char *str1, const char *str2, size_t n )
194 {
195     const unsigned char *ustr1 = (const unsigned char *)str1;
196     const unsigned char *ustr2 = (const unsigned char *)str2;
197     int res;
198
199     if (!n) return 0;
200     while ((--n > 0) && *ustr1) {
201         if ((res = toupper(*ustr1) - toupper(*ustr2))) return res;
202         ustr1++;
203         ustr2++;
204     }
205     return toupper(*ustr1) - toupper(*ustr2);
206 }
207 #endif /* HAVE_STRNCASECMP */
208
209 /***********************************************************************
210  *              openpty
211  * NOTE
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.
215  *
216  * FIXME
217  *   We should have a autoconf check for this.
218  */
219 #ifndef HAVE_OPENPTY
220 int openpty(int *master, int *slave, char *name, struct termios *term, struct winsize *winsize)
221 {
222     const char *ptr1, *ptr2;
223     char pts_name[512];
224
225     strcpy (pts_name, "/dev/ptyXY");
226
227     for (ptr1 = "pqrstuvwxyzPQRST"; *ptr1 != 0; ptr1++) {
228         pts_name[8] = *ptr1;
229         for (ptr2 = "0123456789abcdef"; *ptr2 != 0; ptr2++) {
230             pts_name[9] = *ptr2;
231
232             if ((*master = open(pts_name, O_RDWR)) < 0) {
233                 if (errno == ENOENT)
234                     return -1;
235                 else
236                     continue;
237             }
238             pts_name[5] = 't';
239             if ((*slave = open(pts_name, O_RDWR)) < 0) {
240                 pts_name[5] = 'p';
241                 close (*master);
242                 continue;
243             }
244
245             if (term != NULL)
246                 tcsetattr(*slave, TCSANOW, term);
247             if (winsize != NULL)
248                 ioctl(*slave, TIOCSWINSZ, winsize);
249             if (name != NULL)
250                 strcpy(name, pts_name);
251             return *slave;
252         }
253     }
254     errno = EMFILE;
255     return -1;
256 }
257 #endif  /* HAVE_OPENPTY */
258
259 /***********************************************************************
260  *              getnetbyaddr
261  */
262 #ifndef HAVE_GETNETBYADDR
263 struct netent *getnetbyaddr(unsigned long net, int type)
264 {
265     errno = ENOSYS;
266     return NULL;
267 }
268 #endif /* defined(HAVE_GETNETBYNAME) */
269
270 /***********************************************************************
271  *              getnetbyname
272  */
273 #ifndef HAVE_GETNETBYNAME
274 struct netent *getnetbyname(const char *name)
275 {
276     errno = ENOSYS;
277     return NULL;
278 }
279 #endif /* defined(HAVE_GETNETBYNAME) */
280
281 /***********************************************************************
282  *              getprotobyname
283  */
284 #ifndef HAVE_GETPROTOBYNAME
285 struct protoent *getprotobyname(const char *name)
286 {
287     errno = ENOSYS;
288     return NULL;
289 }
290 #endif /* !defined(HAVE_GETPROTOBYNAME) */
291
292 /***********************************************************************
293  *              getprotobynumber
294  */
295 #ifndef HAVE_GETPROTOBYNUMBER
296 struct protoent *getprotobynumber(int proto)
297 {
298     errno = ENOSYS;
299     return NULL;
300 }
301 #endif /* !defined(HAVE_GETPROTOBYNUMBER) */
302
303 /***********************************************************************
304  *              getservbyport
305  */
306 #ifndef HAVE_GETSERVBYPORT
307 struct servent *getservbyport(int port, const char *proto)
308 {
309     errno = ENOSYS;
310     return NULL;
311 }
312 #endif /* !defined(HAVE_GETSERVBYPORT) */
313
314 /***********************************************************************
315  *              getsockopt
316  */
317 #ifndef HAVE_GETSOCKOPT
318 int getsockopt(int socket, int level, int option_name,
319                void *option_value, size_t *option_len)
320 {
321     errno = ENOSYS;
322     return -1;
323 }
324 #endif /* !defined(HAVE_GETSOCKOPT) */
325
326 /***********************************************************************
327  *              inet_network
328  */
329 #ifndef HAVE_INET_NETWORK
330 unsigned long inet_network(const char *cp)
331 {
332     errno = ENOSYS;
333     return 0;
334 }
335 #endif /* defined(HAVE_INET_NETWORK) */
336
337 /***********************************************************************
338  *              statfs
339  */
340 #ifndef HAVE_STATFS
341 int statfs(const char *name, struct statfs *info)
342 {
343 #ifdef __BEOS__
344     dev_t mydev;
345     fs_info fsinfo;
346
347     if(!info) {
348         errno = ENOSYS;
349         return -1;
350     }
351
352     if ((mydev = dev_for_path(name)) < 0) {
353         errno = ENOSYS;
354         return -1;
355     }
356
357     if (fs_stat_dev(mydev,&fsinfo) < 0) {
358         errno = ENOSYS;
359         return -1;
360     }
361
362     info->f_bsize = fsinfo.block_size;
363     info->f_blocks = fsinfo.total_blocks;
364     info->f_bfree = fsinfo.free_blocks;
365     return 0;
366 #else /* defined(__BEOS__) */
367     errno = ENOSYS;
368     return -1;
369 #endif /* defined(__BEOS__) */
370 }
371 #endif /* !defined(HAVE_STATFS) */
372
373
374 /***********************************************************************
375  *              lstat
376  */
377 #ifndef HAVE_LSTAT
378 int lstat(const char *file_name, struct stat *buf)
379 {
380     return stat( file_name, buf );
381 }
382 #endif /* HAVE_LSTAT */
383
384
385 /***********************************************************************
386  *              pread
387  *
388  * FIXME: this is not thread-safe
389  */
390 #ifndef HAVE_PREAD
391 ssize_t pread( int fd, void *buf, size_t count, off_t offset )
392 {
393     ssize_t ret;
394     off_t old_pos;
395
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)
399     {
400         int err = errno;  /* save errno */
401         lseek( fd, old_pos, SEEK_SET );
402         errno = err;
403         return -1;
404     }
405     if (lseek( fd, old_pos, SEEK_SET ) == -1) return -1;
406     return ret;
407 }
408 #endif /* HAVE_PREAD */
409
410
411 /***********************************************************************
412  *              pwrite
413  *
414  * FIXME: this is not thread-safe
415  */
416 #ifndef HAVE_PWRITE
417 ssize_t pwrite( int fd, const void *buf, size_t count, off_t offset )
418 {
419     ssize_t ret;
420     off_t old_pos;
421
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)
425     {
426         int err = errno;  /* save errno */
427         lseek( fd, old_pos, SEEK_SET );
428         errno = err;
429         return -1;
430     }
431     if (lseek( fd, old_pos, SEEK_SET ) == -1) return -1;
432     return ret;
433 }
434 #endif /* HAVE_PWRITE */
435
436
437 /***********************************************************************
438  *              getrlimit
439  */
440 #ifndef HAVE_GETRLIMIT
441 int getrlimit (int resource, struct rlimit *rlim)
442 {
443     return -1; /* FAIL */
444 }
445 #endif /* HAVE_GETRLIMIT */
446
447
448 #if defined(__svr4__) || defined(__NetBSD__)
449 /***********************************************************************
450  *             try_mmap_fixed
451  *
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.
458  *
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.
465  */
466 static int try_mmap_fixed (void *addr, size_t len, int prot, int flags,
467                            int fildes, off_t off)
468 {
469     char * volatile result = NULL;
470     int pagesize = getpagesize();
471     pid_t pid;
472
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. */
476
477     if ( !addr )
478         return 0;
479     if ( (uintptr_t)addr & (pagesize-1) )
480         return 0;
481     if ( flags & MAP_FIXED )
482         return 0;
483
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. */
490
491     if ( (pid = vfork()) == -1 )
492     {
493         perror("try_mmap_fixed: vfork");
494         exit(1);
495     }
496     if ( pid == 0 )
497     {
498         int i;
499         char vec;
500
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 )
506                _exit(1);
507
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 )
512             _exit(0);
513
514         if ( result != (void *) -1 ) /* This should never happen ... */
515             munmap( result, len );
516
517        _exit(1);
518     }
519
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. */
523
524     return result == addr;
525 }
526 #endif
527
528 /***********************************************************************
529  *              wine_anon_mmap
530  *
531  * Portable wrapper for anonymous mmaps
532  */
533 void *wine_anon_mmap( void *start, size_t size, int prot, int flags )
534 {
535     static int fdzero = -1;
536
537 #ifdef MAP_ANON
538     flags |= MAP_ANON;
539 #else
540     if (fdzero == -1)
541     {
542         if ((fdzero = open( "/dev/zero", O_RDONLY )) == -1)
543         {
544             perror( "/dev/zero: open" );
545             exit(1);
546         }
547     }
548 #endif  /* MAP_ANON */
549
550 #ifdef MAP_SHARED
551     flags &= ~MAP_SHARED;
552 #endif
553
554     /* Linux EINVAL's on us if we don't pass MAP_PRIVATE to an anon mmap */
555 #ifdef MAP_PRIVATE
556     flags |= MAP_PRIVATE;
557 #endif
558
559 #if defined(__svr4__) || defined(__NetBSD__)
560     if ( try_mmap_fixed( start, size, prot, flags, fdzero, 0 ) )
561         return start;
562 #endif
563
564     return mmap( start, size, prot, flags, fdzero, 0 );
565 }
566
567
568 /*
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.
576  */
577
578 /***********************************************************************
579  *              wine_dlopen
580  */
581 void *wine_dlopen( const char *filename, int flag, char *error, int errorsize )
582 {
583 #ifdef HAVE_DLOPEN
584     void *ret;
585     char *s;
586     dlerror(); dlerror();
587     ret = dlopen( filename, flag );
588     s = dlerror();
589     if (error)
590     {
591         strncpy( error, s ? s : "", errorsize );
592         error[errorsize - 1] = '\0';
593     }
594     dlerror();
595     return ret;
596 #else
597     if (error)
598     {
599         strncpy( error, "dlopen interface not detected by configure", errorsize );
600         error[errorsize - 1] = '\0';
601     }
602     return NULL;
603 #endif
604 }
605
606 /***********************************************************************
607  *              wine_dlsym
608  */
609 void *wine_dlsym( void *handle, const char *symbol, char *error, int errorsize )
610 {
611 #ifdef HAVE_DLOPEN
612     void *ret;
613     char *s;
614     dlerror(); dlerror();
615     ret = dlsym( handle, symbol );
616     s = dlerror();
617     if (error)
618     {
619         strncpy( error, s ? s : "", errorsize );
620         error[errorsize - 1] = '\0';
621     }
622     dlerror();
623     return ret;
624 #else
625     if (error)
626     {
627         strncpy( error, "dlopen interface not detected by configure", errorsize );
628         error[errorsize - 1] = '\0';
629     }
630     return NULL;
631 #endif
632 }
633
634 /***********************************************************************
635  *              wine_dlclose
636  */
637 int wine_dlclose( void *handle, char *error, int errorsize )
638 {
639 #ifdef HAVE_DLOPEN
640     int ret;
641     char *s;
642     dlerror(); dlerror();
643     ret = dlclose( handle );
644     s = dlerror();
645     if (error)
646     {
647         strncpy( error, s ? s : "", errorsize );
648         error[errorsize - 1] = '\0';
649     }
650     dlerror();
651     return ret;
652 #else
653     if (error)
654     {
655         strncpy( error, "dlopen interface not detected by configure", errorsize );
656         error[errorsize - 1] = '\0';
657     }
658     return 1;
659 #endif
660 }
661
662 /***********************************************************************
663  *              wine_rewrite_s4tos2
664  *
665  * Convert 4 byte Unicode strings to 2 byte Unicode strings in-place.
666  * This is only practical if literal strings are writable.
667  */
668 unsigned short* wine_rewrite_s4tos2(const wchar_t* str4 )
669 {
670     unsigned short *str2,*s2;
671
672     if (str4==NULL)
673       return NULL;
674
675     if ((*str4 & 0xffff0000) != 0) {
676         /* This string has already been converted. Return it as is */
677         return (unsigned short*)str4;
678     }
679
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.
683      */
684     str2=s2=(unsigned short*)str4;
685     do {
686         *s2=(unsigned short)*str4;
687         s2++;
688     } while (*str4++ != L'\0');
689
690     return str2;
691 }
692
693 #ifndef HAVE_ECVT
694 /*
695  * NetBSD 1.5 doesn't have ecvt, fcvt, gcvt. We just check for ecvt, though.
696  * Fix/verify these implementations !
697  */
698
699 /***********************************************************************
700  *              ecvt
701  */
702 char *ecvt (double number, int  ndigits,  int  *decpt,  int *sign)
703 {
704     static char buf[40]; /* ought to be enough */
705     char *dec;
706     sprintf(buf, "%.*e", ndigits /* FIXME wrong */, number); 
707     *sign = (number < 0);
708     dec = strchr(buf, '.');
709     *decpt = (dec) ? (int)dec - (int)buf : -1;
710     return buf;
711 }
712
713 /***********************************************************************
714  *              fcvt
715  */
716 char *fcvt (double number, int  ndigits,  int  *decpt,  int *sign)
717 {
718     static char buf[40]; /* ought to be enough */
719     char *dec;
720     sprintf(buf, "%.*e", ndigits, number);
721     *sign = (number < 0);
722     dec = strchr(buf, '.');
723     *decpt = (dec) ? (int)dec - (int)buf : -1;
724     return buf;
725 }
726
727 /***********************************************************************
728  *              gcvt
729  *
730  * FIXME: uses both E and F.
731  */
732 char *gcvt (double number, size_t  ndigit,  char *buff)
733 {
734     sprintf(buff, "%.*E", (int)ndigit, number);
735     return buff;
736 }
737 #endif /* HAVE_ECVT */