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