Add to MANIFEST: README.threads, lib/ISA.pm, lib/Class/Fields.pm
[p5sagit/p5-mst-13.2.git] / win32 / win32io.c
CommitLineData
68dc0745 1
2#ifdef __cplusplus
3extern "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>
5aabfad6 19#include <direct.h>
68dc0745 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
28static int *
29dummy_errno(void)
30{
31 return (&(errno));
32}
33
dcb2879a 34static char ***
35dummy_environ(void)
36{
37 return (&(_environ));
38}
39
68dc0745 40/* the rest are the remapped stdio routines */
41static FILE *
42dummy_stderr(void)
43{
44 return stderr;
45}
46
47static FILE *
48dummy_stdin(void)
49{
50 return stdin;
51}
52
53static FILE *
54dummy_stdout(void)
55{
56 return stdout;
57}
58
59static int
60dummy_globalmode(int mode)
61{
62 int o = _fmode;
63 _fmode = mode;
64
65 return o;
66}
67
137443ea 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
68dc0745 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
83EXT_C_FUNC int __cdecl _alloc_osfhnd(void);
84EXT_C_FUNC int __cdecl _set_osfhnd(int fh, long value);
85EXT_C_FUNC void __cdecl _lock_fhandle(int);
86EXT_C_FUNC void __cdecl _unlock_fhandle(int);
87EXT_C_FUNC void __cdecl _unlock(int);
88
89#if (_MSC_VER >= 1000)
90typedef 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
100EXT_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) */
108extern 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
141int
142my_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
180int __cdecl
137443ea 181my_open_osfhandle(long osfhandle, int flags)
68dc0745 182{
183 return _open_osfhandle(osfhandle, flags);
184}
185#endif /* _M_IX86 */
186
187long
188my_get_osfhandle( int filehandle )
189{
190 return _get_osfhandle(filehandle);
191}
192
c90c0ff4 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
200int
201my_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
54310121 239#ifdef PERLDLL
240__declspec(dllexport)
241#endif
68dc0745 242WIN32_IOSUBSYSTEM win32stdio = {
243 12345678L, /* begin of structure; */
244 dummy_errno, /* (*pfunc_errno)(void); */
dcb2879a 245 dummy_environ, /* (*pfunc_environ)(void); */
68dc0745 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,
5aabfad6 293 _mkdir,
294 _rmdir,
295 _chdir,
c90c0ff4 296 my_flock, /* (*pfunc_flock)(int fd, int oper) */
68dc0745 297 87654321L, /* end of structure */
298};
299
300
301#ifdef __cplusplus
302}
303#endif
304