[inseparable changes from changes to perl-5.004_01-mt2]
[p5sagit/p5-mst-13.2.git] / win32 / win32io.c
1
2 #ifdef __cplusplus
3 extern "C" {
4 #endif
5
6 #define WIN32_LEAN_AND_MEAN
7 #define WIN32IO_IS_STDIO
8 #define EXT
9 #include <windows.h>
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <io.h>
13 #include <sys/stat.h>
14 #include <sys/socket.h>
15 #include <fcntl.h>
16 #include <assert.h>
17 #include <errno.h>
18 #include <process.h>
19 #include <direct.h>
20 #include "win32iop.h"
21
22 /*
23  * The following is just a basic wrapping of the stdio
24  *
25  *  redirected io subsystem for all XS modules
26  */
27
28 static int *
29 dummy_errno(void)
30 {
31     return (&(errno));
32 }
33
34 static char ***
35 dummy_environ(void)
36 {
37     return (&(_environ));
38 }
39
40 /* the rest are the remapped stdio routines */
41 static FILE *
42 dummy_stderr(void)
43 {
44     return stderr;
45 }
46
47 static FILE *
48 dummy_stdin(void)
49 {
50     return stdin;
51 }
52
53 static FILE *
54 dummy_stdout(void)
55 {
56     return stdout;
57 }
58
59 static int
60 dummy_globalmode(int mode)
61 {
62     int o = _fmode;
63     _fmode = mode;
64
65     return o;
66 }
67
68 #ifdef _DLL
69 /* It may or may not be fixed (ok on NT), but DLL runtime
70    does not export the functions used in the workround
71 */
72 #define WIN95_OSFHANDLE_FIXED
73 #endif
74
75 #if defined(_WIN32) && !defined(WIN95_OSFHANDLE_FIXED) && defined(_M_IX86)
76
77 #       ifdef __cplusplus
78 #define EXT_C_FUNC      extern "C"
79 #       else
80 #define EXT_C_FUNC      extern
81 #       endif
82
83 EXT_C_FUNC int __cdecl _alloc_osfhnd(void);
84 EXT_C_FUNC int __cdecl _set_osfhnd(int fh, long value);
85 EXT_C_FUNC void __cdecl _lock_fhandle(int);
86 EXT_C_FUNC void __cdecl _unlock_fhandle(int);
87 EXT_C_FUNC void __cdecl _unlock(int);
88
89 #if     (_MSC_VER >= 1000)
90 typedef struct  {
91     long osfhnd;    /* underlying OS file HANDLE */
92     char osfile;    /* attributes of file (e.g., open in text mode?) */
93     char pipech;    /* one char buffer for handles opened on pipes */
94 #if defined (_MT) && !defined (DLL_FOR_WIN32S)
95     int lockinitflag;
96     CRITICAL_SECTION lock;
97 #endif  /* defined (_MT) && !defined (DLL_FOR_WIN32S) */
98 }       ioinfo;
99
100 EXT_C_FUNC ioinfo * __pioinfo[];
101
102 #define IOINFO_L2E                      5
103 #define IOINFO_ARRAY_ELTS       (1 << IOINFO_L2E)
104 #define _pioinfo(i)     (__pioinfo[i >> IOINFO_L2E] + (i & (IOINFO_ARRAY_ELTS - 1)))
105 #define _osfile(i)      (_pioinfo(i)->osfile)
106
107 #else   /* (_MSC_VER >= 1000) */
108 extern char _osfile[];
109 #endif  /* (_MSC_VER >= 1000) */
110
111 #define FOPEN                   0x01    /* file handle open */
112 #define FAPPEND                 0x20    /* file handle opened O_APPEND */
113 #define FDEV                    0x40    /* file handle refers to device */
114 #define FTEXT                   0x80    /* file handle is in text mode */
115
116 #define _STREAM_LOCKS   26              /* Table of stream locks */
117 #define _LAST_STREAM_LOCK  (_STREAM_LOCKS+_NSTREAM_-1)  /* Last stream lock */
118 #define _FH_LOCKS          (_LAST_STREAM_LOCK+1)        /* Table of fh locks */
119
120 /***
121 *int _patch_open_osfhandle(long osfhandle, int flags) - open C Runtime file handle
122 *
123 *Purpose:
124 *       This function allocates a free C Runtime file handle and associates
125 *       it with the Win32 HANDLE specified by the first parameter. This is a
126 *               temperary fix for WIN95's brain damage GetFileType() error on socket
127 *               we just bypass that call for socket
128 *
129 *Entry:
130 *       long osfhandle - Win32 HANDLE to associate with C Runtime file handle.
131 *       int flags      - flags to associate with C Runtime file handle.
132 *
133 *Exit:
134 *       returns index of entry in fh, if successful
135 *       return -1, if no free entry is found
136 *
137 *Exceptions:
138 *
139 *******************************************************************************/
140
141 int
142 my_open_osfhandle(long osfhandle, int flags)
143 {
144     int fh;
145     char fileflags;             /* _osfile flags */
146
147     /* copy relevant flags from second parameter */
148     fileflags = FDEV;
149
150     if(flags & _O_APPEND)
151         fileflags |= FAPPEND;
152
153     if(flags & _O_TEXT)
154         fileflags |= FTEXT;
155
156     /* attempt to allocate a C Runtime file handle */
157     if((fh = _alloc_osfhnd()) == -1) {
158         errno = EMFILE;         /* too many open files */
159         _doserrno = 0L;         /* not an OS error */
160         return -1;              /* return error to caller */
161     }
162
163     /* the file is open. now, set the info in _osfhnd array */
164     _set_osfhnd(fh, osfhandle);
165
166     fileflags |= FOPEN;         /* mark as open */
167
168 #if (_MSC_VER >= 1000)
169     _osfile(fh) = fileflags;    /* set osfile entry */
170     _unlock_fhandle(fh);
171 #else
172     _osfile[fh] = fileflags;    /* set osfile entry */
173     _unlock(fh+_FH_LOCKS);              /* unlock handle */
174 #endif
175
176     return fh;                  /* return handle */
177 }
178 #else
179
180 int __cdecl
181 my_open_osfhandle(long osfhandle, int flags)
182 {
183     return _open_osfhandle(osfhandle, flags);
184 }
185 #endif  /* _M_IX86 */
186
187 long
188 my_get_osfhandle( int filehandle )
189 {
190     return _get_osfhandle(filehandle);
191 }
192
193
194 /* simulate flock by locking a range on the file */
195
196
197 #define LK_ERR(f,i)     ((f) ? (i = 0) : (errno = GetLastError()))
198 #define LK_LEN          0xffff0000
199
200 int
201 my_flock(int fd, int oper)
202 {
203     OVERLAPPED o;
204     int i = -1;
205     HANDLE fh;
206
207     fh = (HANDLE)my_get_osfhandle(fd);
208     memset(&o, 0, sizeof(o));
209
210     switch(oper) {
211     case LOCK_SH:               /* shared lock */
212         LK_ERR(LockFileEx(fh, 0, 0, LK_LEN, 0, &o),i);
213         break;
214     case LOCK_EX:               /* exclusive lock */
215         LK_ERR(LockFileEx(fh, LOCKFILE_EXCLUSIVE_LOCK, 0, LK_LEN, 0, &o),i);
216         break;
217     case LOCK_SH|LOCK_NB:       /* non-blocking shared lock */
218         LK_ERR(LockFileEx(fh, LOCKFILE_FAIL_IMMEDIATELY, 0, LK_LEN, 0, &o),i);
219         break;
220     case LOCK_EX|LOCK_NB:       /* non-blocking exclusive lock */
221         LK_ERR(LockFileEx(fh,
222                        LOCKFILE_EXCLUSIVE_LOCK|LOCKFILE_FAIL_IMMEDIATELY,
223                        0, LK_LEN, 0, &o),i);
224         break;
225     case LOCK_UN:               /* unlock lock */
226         LK_ERR(UnlockFileEx(fh, 0, LK_LEN, 0, &o),i);
227         break;
228     default:                    /* unknown */
229         errno = EINVAL;
230         break;
231     }
232     return i;
233 }
234
235 #undef LK_ERR
236 #undef LK_LEN
237
238
239 #ifdef PERLDLL
240 __declspec(dllexport)
241 #endif
242 WIN32_IOSUBSYSTEM       win32stdio = {
243     12345678L,          /* begin of structure; */
244     dummy_errno,        /* (*pfunc_errno)(void); */
245     dummy_environ,      /* (*pfunc_environ)(void); */
246     dummy_stdin,        /* (*pfunc_stdin)(void); */
247     dummy_stdout,       /* (*pfunc_stdout)(void); */
248     dummy_stderr,       /* (*pfunc_stderr)(void); */
249     ferror,             /* (*pfunc_ferror)(FILE *fp); */
250     feof,               /* (*pfunc_feof)(FILE *fp); */
251     strerror,           /* (*strerror)(int e); */
252     vfprintf,           /* (*pfunc_vfprintf)(FILE *pf, const char *format, va_list arg); */
253     vprintf,            /* (*pfunc_vprintf)(const char *format, va_list arg); */
254     fread,              /* (*pfunc_fread)(void *buf, size_t size, size_t count, FILE *pf); */
255     fwrite,             /* (*pfunc_fwrite)(void *buf, size_t size, size_t count, FILE *pf); */
256     fopen,              /* (*pfunc_fopen)(const char *path, const char *mode); */
257     fdopen,             /* (*pfunc_fdopen)(int fh, const char *mode); */
258     freopen,            /* (*pfunc_freopen)(const char *path, const char *mode, FILE *pf); */
259     fclose,             /* (*pfunc_fclose)(FILE *pf); */
260     fputs,              /* (*pfunc_fputs)(const char *s,FILE *pf); */
261     fputc,              /* (*pfunc_fputc)(int c,FILE *pf); */
262     ungetc,             /* (*pfunc_ungetc)(int c,FILE *pf); */
263     getc,               /* (*pfunc_getc)(FILE *pf); */
264     fileno,             /* (*pfunc_fileno)(FILE *pf); */
265     clearerr,           /* (*pfunc_clearerr)(FILE *pf); */
266     fflush,             /* (*pfunc_fflush)(FILE *pf); */
267     ftell,              /* (*pfunc_ftell)(FILE *pf); */
268     fseek,              /* (*pfunc_fseek)(FILE *pf,long offset,int origin); */
269     fgetpos,            /* (*pfunc_fgetpos)(FILE *pf,fpos_t *p); */
270     fsetpos,            /* (*pfunc_fsetpos)(FILE *pf,fpos_t *p); */
271     rewind,             /* (*pfunc_rewind)(FILE *pf); */
272     tmpfile,            /* (*pfunc_tmpfile)(void); */
273     abort,              /* (*pfunc_abort)(void); */
274     fstat,              /* (*pfunc_fstat)(int fd,struct stat *bufptr); */
275     stat,               /* (*pfunc_stat)(const char *name,struct stat *bufptr); */
276     _pipe,              /* (*pfunc_pipe)( int *phandles, unsigned int psize, int textmode ); */
277     _popen,             /* (*pfunc_popen)( const char *command, const char *mode ); */
278     _pclose,            /* (*pfunc_pclose)( FILE *pf); */
279     setmode,            /* (*pfunc_setmode)( int fd, int mode); */
280     lseek,              /* (*pfunc_lseek)( int fd, long offset, int origin); */
281     tell,               /* (*pfunc_tell)( int fd); */
282     dup,                /* (*pfunc_dup)( int fd); */
283     dup2,               /* (*pfunc_dup2)(int h1, int h2); */
284     open,               /* (*pfunc_open)(const char *path, int oflag,...); */
285     close,              /* (*pfunc_close)(int fd); */
286     eof,                /* (*pfunc_eof)(int fd); */
287     read,               /* (*pfunc_read)(int fd, void *buf, unsigned int cnt); */
288     write,              /* (*pfunc_write)(int fd, const void *buf, unsigned int cnt); */
289     dummy_globalmode,   /* (*pfunc_globalmode)(int mode) */
290     my_open_osfhandle,
291     my_get_osfhandle,
292     spawnvpe,
293     _mkdir,
294     _rmdir,
295     _chdir,
296     my_flock,           /* (*pfunc_flock)(int fd, int oper) */
297     87654321L,          /* end of structure */
298 };
299
300
301 #ifdef __cplusplus
302 }
303 #endif
304