[inseparable changes from patch to perl 5.004_04]
[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
3e3baf6d 68#if defined(_DLL) || defined(__BORLANDC__)
137443ea 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
3e3baf6d 150 if(flags & O_APPEND)
68dc0745 151 fileflags |= FAPPEND;
152
3e3baf6d 153 if(flags & O_TEXT)
68dc0745 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
3e3baf6d 193#ifdef __BORLANDC__
194#define _chdir chdir
195#endif
c90c0ff4 196
197/* simulate flock by locking a range on the file */
198
199
200#define LK_ERR(f,i) ((f) ? (i = 0) : (errno = GetLastError()))
201#define LK_LEN 0xffff0000
202
203int
204my_flock(int fd, int oper)
205{
206 OVERLAPPED o;
207 int i = -1;
208 HANDLE fh;
209
210 fh = (HANDLE)my_get_osfhandle(fd);
211 memset(&o, 0, sizeof(o));
212
213 switch(oper) {
214 case LOCK_SH: /* shared lock */
215 LK_ERR(LockFileEx(fh, 0, 0, LK_LEN, 0, &o),i);
216 break;
217 case LOCK_EX: /* exclusive lock */
218 LK_ERR(LockFileEx(fh, LOCKFILE_EXCLUSIVE_LOCK, 0, LK_LEN, 0, &o),i);
219 break;
220 case LOCK_SH|LOCK_NB: /* non-blocking shared lock */
221 LK_ERR(LockFileEx(fh, LOCKFILE_FAIL_IMMEDIATELY, 0, LK_LEN, 0, &o),i);
222 break;
223 case LOCK_EX|LOCK_NB: /* non-blocking exclusive lock */
224 LK_ERR(LockFileEx(fh,
225 LOCKFILE_EXCLUSIVE_LOCK|LOCKFILE_FAIL_IMMEDIATELY,
226 0, LK_LEN, 0, &o),i);
227 break;
228 case LOCK_UN: /* unlock lock */
229 LK_ERR(UnlockFileEx(fh, 0, LK_LEN, 0, &o),i);
230 break;
231 default: /* unknown */
232 errno = EINVAL;
233 break;
234 }
235 return i;
236}
237
238#undef LK_ERR
239#undef LK_LEN
240
fb73857a 241EXT int my_fclose(FILE *pf);
c90c0ff4 242
54310121 243#ifdef PERLDLL
244__declspec(dllexport)
245#endif
68dc0745 246WIN32_IOSUBSYSTEM win32stdio = {
247 12345678L, /* begin of structure; */
248 dummy_errno, /* (*pfunc_errno)(void); */
dcb2879a 249 dummy_environ, /* (*pfunc_environ)(void); */
68dc0745 250 dummy_stdin, /* (*pfunc_stdin)(void); */
251 dummy_stdout, /* (*pfunc_stdout)(void); */
252 dummy_stderr, /* (*pfunc_stderr)(void); */
253 ferror, /* (*pfunc_ferror)(FILE *fp); */
254 feof, /* (*pfunc_feof)(FILE *fp); */
255 strerror, /* (*strerror)(int e); */
256 vfprintf, /* (*pfunc_vfprintf)(FILE *pf, const char *format, va_list arg); */
257 vprintf, /* (*pfunc_vprintf)(const char *format, va_list arg); */
258 fread, /* (*pfunc_fread)(void *buf, size_t size, size_t count, FILE *pf); */
259 fwrite, /* (*pfunc_fwrite)(void *buf, size_t size, size_t count, FILE *pf); */
260 fopen, /* (*pfunc_fopen)(const char *path, const char *mode); */
261 fdopen, /* (*pfunc_fdopen)(int fh, const char *mode); */
262 freopen, /* (*pfunc_freopen)(const char *path, const char *mode, FILE *pf); */
fb73857a 263 my_fclose, /* (*pfunc_fclose)(FILE *pf); */
68dc0745 264 fputs, /* (*pfunc_fputs)(const char *s,FILE *pf); */
265 fputc, /* (*pfunc_fputc)(int c,FILE *pf); */
266 ungetc, /* (*pfunc_ungetc)(int c,FILE *pf); */
267 getc, /* (*pfunc_getc)(FILE *pf); */
268 fileno, /* (*pfunc_fileno)(FILE *pf); */
269 clearerr, /* (*pfunc_clearerr)(FILE *pf); */
270 fflush, /* (*pfunc_fflush)(FILE *pf); */
271 ftell, /* (*pfunc_ftell)(FILE *pf); */
272 fseek, /* (*pfunc_fseek)(FILE *pf,long offset,int origin); */
273 fgetpos, /* (*pfunc_fgetpos)(FILE *pf,fpos_t *p); */
274 fsetpos, /* (*pfunc_fsetpos)(FILE *pf,fpos_t *p); */
275 rewind, /* (*pfunc_rewind)(FILE *pf); */
276 tmpfile, /* (*pfunc_tmpfile)(void); */
277 abort, /* (*pfunc_abort)(void); */
278 fstat, /* (*pfunc_fstat)(int fd,struct stat *bufptr); */
279 stat, /* (*pfunc_stat)(const char *name,struct stat *bufptr); */
280 _pipe, /* (*pfunc_pipe)( int *phandles, unsigned int psize, int textmode ); */
281 _popen, /* (*pfunc_popen)( const char *command, const char *mode ); */
282 _pclose, /* (*pfunc_pclose)( FILE *pf); */
283 setmode, /* (*pfunc_setmode)( int fd, int mode); */
284 lseek, /* (*pfunc_lseek)( int fd, long offset, int origin); */
285 tell, /* (*pfunc_tell)( int fd); */
286 dup, /* (*pfunc_dup)( int fd); */
287 dup2, /* (*pfunc_dup2)(int h1, int h2); */
288 open, /* (*pfunc_open)(const char *path, int oflag,...); */
289 close, /* (*pfunc_close)(int fd); */
290 eof, /* (*pfunc_eof)(int fd); */
291 read, /* (*pfunc_read)(int fd, void *buf, unsigned int cnt); */
292 write, /* (*pfunc_write)(int fd, const void *buf, unsigned int cnt); */
293 dummy_globalmode, /* (*pfunc_globalmode)(int mode) */
294 my_open_osfhandle,
295 my_get_osfhandle,
3e3baf6d 296 spawnvp,
84902520 297 mkdir,
298 rmdir,
299 chdir,
c90c0ff4 300 my_flock, /* (*pfunc_flock)(int fd, int oper) */
6890e559 301 execvp,
84902520 302 perror,
303 setbuf,
304 setvbuf,
305 flushall,
306 fcloseall,
307 fgets,
308 gets,
309 fgetc,
310 putc,
311 puts,
312 getchar,
313 putchar,
314 fscanf,
315 scanf,
316 malloc,
317 calloc,
318 realloc,
319 free,
68dc0745 320 87654321L, /* end of structure */
321};
322
323
324#ifdef __cplusplus
325}
326#endif
327