#ifdef __cplusplus extern "C" { #endif #define WIN32_LEAN_AND_MEAN #define WIN32IO_IS_STDIO #define EXT #include #include #include #include #include #include #include #include #include #include #include #include "win32iop.h" /* * The following is just a basic wrapping of the stdio * * redirected io subsystem for all XS modules */ static int * dummy_errno(void) { return (&(errno)); } static char *** dummy_environ(void) { return (&(_environ)); } /* the rest are the remapped stdio routines */ static FILE * dummy_stderr(void) { return stderr; } static FILE * dummy_stdin(void) { return stdin; } static FILE * dummy_stdout(void) { return stdout; } static int dummy_globalmode(int mode) { int o = _fmode; _fmode = mode; return o; } #ifdef _DLL /* It may or may not be fixed (ok on NT), but DLL runtime does not export the functions used in the workround */ #define WIN95_OSFHANDLE_FIXED #endif #if defined(_WIN32) && !defined(WIN95_OSFHANDLE_FIXED) && defined(_M_IX86) # ifdef __cplusplus #define EXT_C_FUNC extern "C" # else #define EXT_C_FUNC extern # endif EXT_C_FUNC int __cdecl _alloc_osfhnd(void); EXT_C_FUNC int __cdecl _set_osfhnd(int fh, long value); EXT_C_FUNC void __cdecl _lock_fhandle(int); EXT_C_FUNC void __cdecl _unlock_fhandle(int); EXT_C_FUNC void __cdecl _unlock(int); #if (_MSC_VER >= 1000) typedef struct { long osfhnd; /* underlying OS file HANDLE */ char osfile; /* attributes of file (e.g., open in text mode?) */ char pipech; /* one char buffer for handles opened on pipes */ #if defined (_MT) && !defined (DLL_FOR_WIN32S) int lockinitflag; CRITICAL_SECTION lock; #endif /* defined (_MT) && !defined (DLL_FOR_WIN32S) */ } ioinfo; EXT_C_FUNC ioinfo * __pioinfo[]; #define IOINFO_L2E 5 #define IOINFO_ARRAY_ELTS (1 << IOINFO_L2E) #define _pioinfo(i) (__pioinfo[i >> IOINFO_L2E] + (i & (IOINFO_ARRAY_ELTS - 1))) #define _osfile(i) (_pioinfo(i)->osfile) #else /* (_MSC_VER >= 1000) */ extern char _osfile[]; #endif /* (_MSC_VER >= 1000) */ #define FOPEN 0x01 /* file handle open */ #define FAPPEND 0x20 /* file handle opened O_APPEND */ #define FDEV 0x40 /* file handle refers to device */ #define FTEXT 0x80 /* file handle is in text mode */ #define _STREAM_LOCKS 26 /* Table of stream locks */ #define _LAST_STREAM_LOCK (_STREAM_LOCKS+_NSTREAM_-1) /* Last stream lock */ #define _FH_LOCKS (_LAST_STREAM_LOCK+1) /* Table of fh locks */ /*** *int _patch_open_osfhandle(long osfhandle, int flags) - open C Runtime file handle * *Purpose: * This function allocates a free C Runtime file handle and associates * it with the Win32 HANDLE specified by the first parameter. This is a * temperary fix for WIN95's brain damage GetFileType() error on socket * we just bypass that call for socket * *Entry: * long osfhandle - Win32 HANDLE to associate with C Runtime file handle. * int flags - flags to associate with C Runtime file handle. * *Exit: * returns index of entry in fh, if successful * return -1, if no free entry is found * *Exceptions: * *******************************************************************************/ int my_open_osfhandle(long osfhandle, int flags) { int fh; char fileflags; /* _osfile flags */ /* copy relevant flags from second parameter */ fileflags = FDEV; if(flags & _O_APPEND) fileflags |= FAPPEND; if(flags & _O_TEXT) fileflags |= FTEXT; /* attempt to allocate a C Runtime file handle */ if((fh = _alloc_osfhnd()) == -1) { errno = EMFILE; /* too many open files */ _doserrno = 0L; /* not an OS error */ return -1; /* return error to caller */ } /* the file is open. now, set the info in _osfhnd array */ _set_osfhnd(fh, osfhandle); fileflags |= FOPEN; /* mark as open */ #if (_MSC_VER >= 1000) _osfile(fh) = fileflags; /* set osfile entry */ _unlock_fhandle(fh); #else _osfile[fh] = fileflags; /* set osfile entry */ _unlock(fh+_FH_LOCKS); /* unlock handle */ #endif return fh; /* return handle */ } #else int __cdecl my_open_osfhandle(long osfhandle, int flags) { return _open_osfhandle(osfhandle, flags); } #endif /* _M_IX86 */ long my_get_osfhandle( int filehandle ) { return _get_osfhandle(filehandle); } /* simulate flock by locking a range on the file */ #define LK_ERR(f,i) ((f) ? (i = 0) : (errno = GetLastError())) #define LK_LEN 0xffff0000 int my_flock(int fd, int oper) { OVERLAPPED o; int i = -1; HANDLE fh; fh = (HANDLE)my_get_osfhandle(fd); memset(&o, 0, sizeof(o)); switch(oper) { case LOCK_SH: /* shared lock */ LK_ERR(LockFileEx(fh, 0, 0, LK_LEN, 0, &o),i); break; case LOCK_EX: /* exclusive lock */ LK_ERR(LockFileEx(fh, LOCKFILE_EXCLUSIVE_LOCK, 0, LK_LEN, 0, &o),i); break; case LOCK_SH|LOCK_NB: /* non-blocking shared lock */ LK_ERR(LockFileEx(fh, LOCKFILE_FAIL_IMMEDIATELY, 0, LK_LEN, 0, &o),i); break; case LOCK_EX|LOCK_NB: /* non-blocking exclusive lock */ LK_ERR(LockFileEx(fh, LOCKFILE_EXCLUSIVE_LOCK|LOCKFILE_FAIL_IMMEDIATELY, 0, LK_LEN, 0, &o),i); break; case LOCK_UN: /* unlock lock */ LK_ERR(UnlockFileEx(fh, 0, LK_LEN, 0, &o),i); break; default: /* unknown */ errno = EINVAL; break; } return i; } #undef LK_ERR #undef LK_LEN #ifdef PERLDLL __declspec(dllexport) #endif WIN32_IOSUBSYSTEM win32stdio = { 12345678L, /* begin of structure; */ dummy_errno, /* (*pfunc_errno)(void); */ dummy_environ, /* (*pfunc_environ)(void); */ dummy_stdin, /* (*pfunc_stdin)(void); */ dummy_stdout, /* (*pfunc_stdout)(void); */ dummy_stderr, /* (*pfunc_stderr)(void); */ ferror, /* (*pfunc_ferror)(FILE *fp); */ feof, /* (*pfunc_feof)(FILE *fp); */ strerror, /* (*strerror)(int e); */ vfprintf, /* (*pfunc_vfprintf)(FILE *pf, const char *format, va_list arg); */ vprintf, /* (*pfunc_vprintf)(const char *format, va_list arg); */ fread, /* (*pfunc_fread)(void *buf, size_t size, size_t count, FILE *pf); */ fwrite, /* (*pfunc_fwrite)(void *buf, size_t size, size_t count, FILE *pf); */ fopen, /* (*pfunc_fopen)(const char *path, const char *mode); */ fdopen, /* (*pfunc_fdopen)(int fh, const char *mode); */ freopen, /* (*pfunc_freopen)(const char *path, const char *mode, FILE *pf); */ fclose, /* (*pfunc_fclose)(FILE *pf); */ fputs, /* (*pfunc_fputs)(const char *s,FILE *pf); */ fputc, /* (*pfunc_fputc)(int c,FILE *pf); */ ungetc, /* (*pfunc_ungetc)(int c,FILE *pf); */ getc, /* (*pfunc_getc)(FILE *pf); */ fileno, /* (*pfunc_fileno)(FILE *pf); */ clearerr, /* (*pfunc_clearerr)(FILE *pf); */ fflush, /* (*pfunc_fflush)(FILE *pf); */ ftell, /* (*pfunc_ftell)(FILE *pf); */ fseek, /* (*pfunc_fseek)(FILE *pf,long offset,int origin); */ fgetpos, /* (*pfunc_fgetpos)(FILE *pf,fpos_t *p); */ fsetpos, /* (*pfunc_fsetpos)(FILE *pf,fpos_t *p); */ rewind, /* (*pfunc_rewind)(FILE *pf); */ tmpfile, /* (*pfunc_tmpfile)(void); */ abort, /* (*pfunc_abort)(void); */ fstat, /* (*pfunc_fstat)(int fd,struct stat *bufptr); */ stat, /* (*pfunc_stat)(const char *name,struct stat *bufptr); */ _pipe, /* (*pfunc_pipe)( int *phandles, unsigned int psize, int textmode ); */ _popen, /* (*pfunc_popen)( const char *command, const char *mode ); */ _pclose, /* (*pfunc_pclose)( FILE *pf); */ setmode, /* (*pfunc_setmode)( int fd, int mode); */ lseek, /* (*pfunc_lseek)( int fd, long offset, int origin); */ tell, /* (*pfunc_tell)( int fd); */ dup, /* (*pfunc_dup)( int fd); */ dup2, /* (*pfunc_dup2)(int h1, int h2); */ open, /* (*pfunc_open)(const char *path, int oflag,...); */ close, /* (*pfunc_close)(int fd); */ eof, /* (*pfunc_eof)(int fd); */ read, /* (*pfunc_read)(int fd, void *buf, unsigned int cnt); */ write, /* (*pfunc_write)(int fd, const void *buf, unsigned int cnt); */ dummy_globalmode, /* (*pfunc_globalmode)(int mode) */ my_open_osfhandle, my_get_osfhandle, spawnvpe, _mkdir, _rmdir, _chdir, my_flock, /* (*pfunc_flock)(int fd, int oper) */ 87654321L, /* end of structure */ }; #ifdef __cplusplus } #endif