/**************************************************************************** * * SciTech MGL Graphics Library * * ======================================================================== * * The contents of this file are subject to the SciTech MGL Public * License Version 1.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.scitechsoft.com/mgl-license.txt * * Software distributed under the License is distributed on an * "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. * * The Original Code is Copyright (C) 1991-1998 SciTech Software, Inc. * * The Initial Developer of the Original Code is SciTech Software, Inc. * All Rights Reserved. * * ======================================================================== * * Language: ANSI C * Environment: Any * * Description: Module to implement a the OS specific side of the Binary * Portable DLL C runtime library. The functions in here * are imported into the Binary Portable DLL's to implement * OS specific services. * ****************************************************************************/ #include "pmapi.h" #if defined(__WIN32_VXD__) || defined(__NT_DRIVER__) #include "drvlib/peloader.h" #include "drvlib/attrib.h" #include "drvlib/libc/init.h" #define __BUILDING_PE_LOADER__ #include "drvlib/libc/file.h" #if defined(__WIN32_VXD__) #include "vxdfile.h" #endif #else #include #include #include #include #include #include #include #if defined(__GNUC__) || defined(__UNIX__) #include #include #include #else #include #endif #include "drvlib/attrib.h" #include "drvlib/libc/init.h" #define __BUILDING_PE_LOADER__ #include "drvlib/libc/file.h" #if defined(__WINDOWS__) || defined(TNT) || defined(__RTTARGET__) #define WIN32_LEAN_AND_MEAN #define STRICT #include #endif #ifdef __MSDOS__ #include #endif #ifdef __OS2__ #define INCL_DOS #define INCL_DOSERRORS #define INCL_SUB #include #endif #endif /* No text or binary modes for Unix */ #ifndef O_BINARY #define O_BINARY 0 #define O_TEXT 0 #endif /*--------------------------- Global variables ----------------------------*/ #if defined(__WIN32_VXD__) || defined(__NT_DRIVER__) #define MAX_FILES 16 static FILE *openHandles[MAX_FILES] = {NULL}; #endif /* stub functions */ void _CDECL stub_abort(void); int _CDECL stub_atexit(void (*)(void)); void * _CDECL stub_calloc(size_t _nelem, size_t _size); void _CDECL stub_exit(int _status); void _CDECL stub_free(void *_ptr); char * _CDECL stub_getenv(const char *_name); void * _CDECL stub_malloc(size_t _size); void * _CDECL stub_realloc(void *_ptr, size_t _size); int _CDECL stub_system(const char *_s); int _CDECL stub_putenv(const char *_val); /* stub functions */ int _CDECL stub_open(const char *_path, int _oflag, unsigned _mode); int _CDECL stub_access(const char *_path, int _amode); int _CDECL stub_close(int _fildes); off_t _CDECL stub_lseek(int _fildes, off_t _offset, int _whence); size_t _CDECL stub_read(int _fildes, void *_buf, size_t _nbyte); int _CDECL stub_unlink(const char *_path); size_t _CDECL stub_write(int _fildes, const void *_buf, size_t _nbyte); int _CDECL stub_isatty(int _fildes); /* stub functions */ int _CDECL stub_remove(const char *_filename); int _CDECL stub_rename(const char *_old, const char *_new); /* stub functions */ time_t _CDECL stub_time(time_t *_tod); /* stub functions */ int _CDECL stub_raise(int); void * _CDECL stub_signal(int, void *); /* functions */ #define stub_OS_setfileattr _OS_setfileattr #define stub_OS_getcurrentdate _OS_getcurrentdate LIBC_imports _VARAPI ___imports = { sizeof(LIBC_imports), /* exports */ stub_abort, stub_atexit, stub_calloc, stub_exit, stub_free, stub_getenv, stub_malloc, stub_realloc, stub_system, stub_putenv, /* exports */ stub_open, stub_access, stub_close, stub_lseek, stub_read, stub_unlink, stub_write, stub_isatty, /* exports */ stub_remove, stub_rename, /* functions */ stub_raise, stub_signal, /* exports */ stub_time, /* exports */ stub_OS_setfileattr, stub_OS_getcurrentdate, }; /*---------------------- Stub function implementation ---------------------*/ /* stub functions */ void _CDECL stub_abort(void) { #if !defined( __WIN32_VXD__) && !defined(__NT_DRIVER__) abort(); #endif } int _CDECL stub_atexit(void (*func)(void)) { #if !defined( __WIN32_VXD__) && !defined(__NT_DRIVER__) return atexit((void(*)(void))func); #else return -1; #endif } void * _CDECL stub_calloc(size_t _nelem, size_t _size) { return __PM_calloc(_nelem,_size); } void _CDECL stub_exit(int _status) { #if !defined( __WIN32_VXD__) && !defined(__NT_DRIVER__) exit(_status); #endif } void _CDECL stub_free(void *_ptr) { __PM_free(_ptr); } char * _CDECL stub_getenv(const char *_name) { #if defined( __WIN32_VXD__) || defined(__NT_DRIVER__) return NULL; #else return getenv(_name); #endif } void * _CDECL stub_malloc(size_t _size) { return __PM_malloc(_size); } void * _CDECL stub_realloc(void *_ptr, size_t _size) { return __PM_realloc(_ptr,_size); } int _CDECL stub_system(const char *_s) { #if defined(__WINDOWS__) || defined(__WIN32_VXD__) || defined(__NT_DRIVER__) || defined(__SMX32__) || defined(__RTTARGET__) (void)_s; return -1; #else return system(_s); #endif } int _CDECL stub_putenv(const char *_val) { #if defined( __WIN32_VXD__) || defined(__NT_DRIVER__) return -1; #else return putenv((char*)_val); #endif } time_t _CDECL stub_time(time_t *_tod) { #if defined( __WIN32_VXD__) || defined(__NT_DRIVER__) return 0; #else return time(_tod); #endif } #if defined(__MSDOS__) #if defined(TNT) && defined(_MSC_VER) void _CDECL _OS_setfileattr(const char *filename,unsigned attrib) { SetFileAttributes((LPSTR)filename, (DWORD)attrib); } #else void _CDECL _OS_setfileattr(const char *filename,unsigned attrib) { _dos_setfileattr(filename,attrib); } #endif #elif defined(__WIN32_VXD__) #define USE_LOCAL_FILEIO #define USE_LOCAL_GETDATE /* stub functions */ int _CDECL stub_open(const char *_path, int _oflag, unsigned _mode) { char mode[10]; int i; /* Find an empty file handle to use */ for (i = 3; i < MAX_FILES; i++) { if (!openHandles[i]) break; } if (openHandles[i]) return -1; /* Find the open flags to use */ if (_oflag & ___O_TRUNC) strcpy(mode,"w"); else if (_oflag & ___O_CREAT) strcpy(mode,"a"); else strcpy(mode,"r"); if (_oflag & ___O_BINARY) strcat(mode,"b"); if (_oflag & ___O_TEXT) strcat(mode,"t"); /* Open the file and store the file handle */ if ((openHandles[i] = fopen(_path,mode)) == NULL) return -1; return i; } int _CDECL stub_access(const char *_path, int _amode) { return -1; } int _CDECL stub_close(int _fildes) { if (_fildes >= 3 && openHandles[_fildes]) { fclose(openHandles[_fildes]); openHandles[_fildes] = NULL; } return 0; } off_t _CDECL stub_lseek(int _fildes, off_t _offset, int _whence) { if (_fildes >= 3) { fseek(openHandles[_fildes],_offset,_whence); return ftell(openHandles[_fildes]); } return 0; } size_t _CDECL stub_read(int _fildes, void *_buf, size_t _nbyte) { if (_fildes >= 3) return fread(_buf,1,_nbyte,openHandles[_fildes]); return 0; } int _CDECL stub_unlink(const char *_path) { WORD error; if (initComplete) { if (R0_DeleteFile((char*)_path,0,&error)) return 0; return -1; } else return i_remove(_path); } size_t _CDECL stub_write(int _fildes, const void *_buf, size_t _nbyte) { if (_fildes >= 3) return fwrite(_buf,1,_nbyte,openHandles[_fildes]); return _nbyte; } int _CDECL stub_isatty(int _fildes) { return 0; } /* stub functions */ int _CDECL stub_remove(const char *_filename) { return stub_unlink(_filename); } int _CDECL stub_rename(const char *_old, const char *_new) { return -1; } void _CDECL _OS_setfileattr(const char *filename,unsigned attrib) { WORD error; if (initComplete) R0_SetFileAttributes((char*)filename,attrib,&error); } /* Return the current date in days since 1/1/1980 */ ulong _CDECL _OS_getcurrentdate(void) { DWORD date; VTD_Get_Date_And_Time(&date); return date; } #elif defined(__NT_DRIVER__) #define USE_LOCAL_FILEIO #define USE_LOCAL_GETDATE /* stub functions */ int _CDECL stub_open(const char *_path, int _oflag, unsigned _mode) { char mode[10]; int i; /* Find an empty file handle to use */ for (i = 3; i < MAX_FILES; i++) { if (!openHandles[i]) break; } if (openHandles[i]) return -1; /* Find the open flags to use */ if (_oflag & ___O_TRUNC) strcpy(mode,"w"); else if (_oflag & ___O_CREAT) strcpy(mode,"a"); else strcpy(mode,"r"); if (_oflag & ___O_BINARY) strcat(mode,"b"); if (_oflag & ___O_TEXT) strcat(mode,"t"); /* Open the file and store the file handle */ if ((openHandles[i] = fopen(_path,mode)) == NULL) return -1; return i; } int _CDECL stub_close(int _fildes) { if (_fildes >= 3 && openHandles[_fildes]) { fclose(openHandles[_fildes]); openHandles[_fildes] = NULL; } return 0; } off_t _CDECL stub_lseek(int _fildes, off_t _offset, int _whence) { if (_fildes >= 3) { fseek(openHandles[_fildes],_offset,_whence); return ftell(openHandles[_fildes]); } return 0; } size_t _CDECL stub_read(int _fildes, void *_buf, size_t _nbyte) { if (_fildes >= 3) return fread(_buf,1,_nbyte,openHandles[_fildes]); return 0; } size_t _CDECL stub_write(int _fildes, const void *_buf, size_t _nbyte) { if (_fildes >= 3) return fwrite(_buf,1,_nbyte,openHandles[_fildes]); return _nbyte; } int _CDECL stub_access(const char *_path, int _amode) { return -1; } int _CDECL stub_isatty(int _fildes) { return 0; } int _CDECL stub_unlink(const char *_path) { /* TODO: Implement this! */ return -1; } /* stub functions */ int _CDECL stub_remove(const char *_filename) { return stub_unlink(_filename); } int _CDECL stub_rename(const char *_old, const char *_new) { /* TODO: Implement this! */ return -1; } void _CDECL _OS_setfileattr(const char *filename,unsigned attrib) { uint _attr = 0; if (attrib & __A_RDONLY) _attr |= FILE_ATTRIBUTE_READONLY; if (attrib & __A_HIDDEN) _attr |= FILE_ATTRIBUTE_HIDDEN; if (attrib & __A_SYSTEM) _attr |= FILE_ATTRIBUTE_SYSTEM; PM_setFileAttr(filename,_attr); } /* Return the current date in days since 1/1/1980 */ ulong _CDECL _OS_getcurrentdate(void) { TIME_FIELDS tm; _int64 count,count_1_1_1980; tm.Year = 1980; tm.Month = 1; tm.Day = 1; tm.Hour = 0; tm.Minute = 0; tm.Second = 0; tm.Milliseconds = 0; tm.Weekday = 0; RtlTimeFieldsToTime(&tm,(PLARGE_INTEGER)&count_1_1_1980); KeQuerySystemTime((PLARGE_INTEGER)&count); return (ulong)( (count - count_1_1_1980) / ((_int64)24 * (_int64)3600 * (_int64)10000000) ); } #elif defined(__WINDOWS32__) || defined(__RTTARGET__) void _CDECL _OS_setfileattr(const char *filename,unsigned attrib) { SetFileAttributes((LPSTR)filename, (DWORD)attrib); } #elif defined(__OS2__) #define USE_LOCAL_FILEIO #ifndef W_OK #define W_OK 0x02 #endif void _CDECL _OS_setfileattr(const char *filename,unsigned attrib) { FILESTATUS3 s; if (DosQueryPathInfo((PSZ)filename,FIL_STANDARD,(PVOID)&s,sizeof(s))) return; s.attrFile = attrib; DosSetPathInfo((PSZ)filename,FIL_STANDARD,(PVOID)&s,sizeof(s),0L); } /* stub functions */ #define BUF_SIZE 4096 /* Note: the implementation of the standard Unix-ish handle-based I/O isn't * complete - but that wasn't the intent either. Note also that we * don't presently support text file I/O, so all text files end * up in Unix format (and are not translated!). */ int _CDECL stub_open(const char *_path, int _oflag, unsigned _mode) { HFILE handle; ULONG error, actiontaken, openflag, openmode; char path[PM_MAX_PATH]; /* Determine open flags */ if (_oflag & ___O_CREAT) { if (_oflag & ___O_EXCL) openflag = OPEN_ACTION_FAIL_IF_EXISTS | OPEN_ACTION_CREATE_IF_NEW; else if (_oflag & ___O_TRUNC) openflag = OPEN_ACTION_REPLACE_IF_EXISTS | OPEN_ACTION_CREATE_IF_NEW; else openflag = OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_CREATE_IF_NEW; } else if (_oflag & ___O_TRUNC) openflag = OPEN_ACTION_REPLACE_IF_EXISTS; else openflag = OPEN_ACTION_OPEN_IF_EXISTS; /* Determine open mode flags */ if (_oflag & ___O_RDONLY) openmode = OPEN_ACCESS_READONLY | OPEN_SHARE_DENYNONE; else if (_oflag & ___O_WRONLY) openmode = OPEN_ACCESS_WRITEONLY | OPEN_SHARE_DENYWRITE; else openmode = OPEN_ACCESS_READWRITE | OPEN_SHARE_DENYWRITE; /* Copy the path to a variable on the stack. We need to do this * for OS/2 as when the drivers are loaded into shared kernel * memory, we can't pass an address from that memory range to * this function. */ strcpy(path,_path); if (DosOpen(path, &handle, &actiontaken, 0, FILE_NORMAL, openflag, openmode, NULL) != NO_ERROR) return -1; /* Handle append mode of operation */ if (_oflag & ___O_APPEND) { if (DosSetFilePtr(handle, 0, FILE_END, &error) != NO_ERROR) return -1; } return handle; } int _CDECL stub_access(const char *_path, int _amode) { char path[PM_MAX_PATH]; FILESTATUS fs; /* Copy the path to a variable on the stack. We need to do this * for OS/2 as when the drivers are loaded into shared kernel * memory, we can't pass an address from that memory range to * this function. */ strcpy(path,_path); if (DosQueryPathInfo(path, FIL_STANDARD, &fs, sizeof(fs)) != NO_ERROR) return -1; if ((_amode & W_OK) && (fs.attrFile & FILE_READONLY)) return -1; return 0; } int _CDECL stub_close(int _fildes) { if (DosClose(_fildes) != NO_ERROR) return -1; return 0; } off_t _CDECL stub_lseek(int _fildes, off_t _offset, int _whence) { ULONG cbActual, origin; switch (_whence) { case SEEK_CUR: origin = FILE_CURRENT; break; case SEEK_END: origin = FILE_END; break; default: origin = FILE_BEGIN; } if (DosSetFilePtr(_fildes, _offset, origin, &cbActual) != NO_ERROR) return -1; return cbActual; } size_t _CDECL stub_read(int _fildes, void *_buf, size_t _nbyte) { ULONG cbActual = 0,cbRead; uchar *p = _buf; uchar file_io_buf[BUF_SIZE]; /* We need to perform the physical read in chunks into a * a temporary static buffer, since the buffer passed in may be * in kernel space and will cause DosRead to bail internally. */ while (_nbyte > BUF_SIZE) { if (DosRead(_fildes, file_io_buf, BUF_SIZE, &cbRead) != NO_ERROR) return -1; cbActual += cbRead; memcpy(p,file_io_buf,BUF_SIZE); p += BUF_SIZE; _nbyte -= BUF_SIZE; } if (_nbyte) { if (DosRead(_fildes, file_io_buf, _nbyte, &cbRead) != NO_ERROR) return -1; cbActual += cbRead; memcpy(p,file_io_buf,_nbyte); } return cbActual; } size_t _CDECL stub_write(int _fildes, const void *_buf, size_t _nbyte) { ULONG cbActual = 0,cbWrite; uchar *p = (PVOID)_buf; uchar file_io_buf[BUF_SIZE]; /* We need to perform the physical write in chunks from a * a temporary static buffer, since the buffer passed in may be * in kernel space and will cause DosWrite to bail internally. */ while (_nbyte > BUF_SIZE) { memcpy(file_io_buf,p,BUF_SIZE); if (DosWrite(_fildes, file_io_buf, BUF_SIZE, &cbWrite) != NO_ERROR) return -1; cbActual += cbWrite; p += BUF_SIZE; _nbyte -= BUF_SIZE; } if (_nbyte) { memcpy(file_io_buf,p,_nbyte); if (DosWrite(_fildes, file_io_buf, _nbyte, &cbWrite) != NO_ERROR) return -1; cbActual += cbWrite; } return cbActual; } int _CDECL stub_unlink(const char *_path) { char path[PM_MAX_PATH]; /* Copy the path to a variable on the stack. We need to do this * for OS/2 as when the drivers are loaded into shared kernel * memory, we can't pass an address from that memory range to * this function. */ strcpy(path,_path); if (DosDelete(path) != NO_ERROR) return -1; return 0; } int _CDECL stub_isatty(int _fildes) { ULONG htype, flags; if (DosQueryHType(_fildes, &htype, &flags) != NO_ERROR) return 0; return ((htype & 0xFF) == HANDTYPE_DEVICE); } /* stub functions */ int _CDECL stub_remove(const char *_path) { char path[PM_MAX_PATH]; /* Copy the path to a variable on the stack. We need to do this * for OS/2 as when the drivers are loaded into shared kernel * memory, we can't pass an address from that memory range to * this function. */ strcpy(path,_path); if (DosDelete(path) != NO_ERROR) return -1; return 0; } int _CDECL stub_rename(const char *_old, const char *_new) { char old[PM_MAX_PATH]; char new[PM_MAX_PATH]; /* Copy the path to a variable on the stack. We need to do this * for OS/2 as when the drivers are loaded into shared kernel * memory, we can't pass an address from that memory range to * this function. */ strcpy(old,_old); strcpy(new,_new); if (DosMove(old, new) != NO_ERROR) return -1; return 0; } #else void _CDECL _OS_setfileattr(const char *filename,unsigned attrib) { /* Unable to set hidden, system attributes on Unix. */ } #endif #ifndef USE_LOCAL_FILEIO /* stub functions */ int _CDECL stub_open(const char *_path, int _oflag, unsigned _mode) { int oflag_tab[] = { ___O_RDONLY, O_RDONLY, ___O_WRONLY, O_WRONLY, ___O_RDWR, O_RDWR, ___O_BINARY, O_BINARY, ___O_TEXT, O_TEXT, ___O_CREAT, O_CREAT, ___O_EXCL, O_EXCL, ___O_TRUNC, O_TRUNC, ___O_APPEND, O_APPEND, }; int i,oflag = 0; /* Translate the oflag's to the OS dependent versions */ for (i = 0; i < sizeof(oflag_tab) / sizeof(int); i += 2) { if (_oflag & oflag_tab[i]) oflag |= oflag_tab[i+1]; } return open(_path,oflag,_mode); } int _CDECL stub_access(const char *_path, int _amode) { return access(_path,_amode); } int _CDECL stub_close(int _fildes) { return close(_fildes); } off_t _CDECL stub_lseek(int _fildes, off_t _offset, int _whence) { return lseek(_fildes,_offset,_whence); } size_t _CDECL stub_read(int _fildes, void *_buf, size_t _nbyte) { return read(_fildes,_buf,_nbyte); } int _CDECL stub_unlink(const char *_path) { return unlink(_path); } size_t _CDECL stub_write(int _fildes, const void *_buf, size_t _nbyte) { return write(_fildes,_buf,_nbyte); } int _CDECL stub_isatty(int _fildes) { return isatty(_fildes); } /* stub functions */ int _CDECL stub_remove(const char *_filename) { return remove(_filename); } int _CDECL stub_rename(const char *_old, const char *_new) { return rename(_old,_new); } #endif #ifndef USE_LOCAL_GETDATE /* Return the current date in days since 1/1/1980 */ ulong _CDECL _OS_getcurrentdate(void) { struct tm refTime; refTime.tm_year = 80; refTime.tm_mon = 0; refTime.tm_mday = 1; refTime.tm_hour = 0; refTime.tm_min = 0; refTime.tm_sec = 0; refTime.tm_isdst = -1; return (time(NULL) - mktime(&refTime)) / (24 * 3600L); } #endif int _CDECL stub_raise(int sig) { #if defined(__WIN32_VXD__) || defined(__NT_DRIVER__) || defined(__SMX32__) return -1; #else return raise(sig); #endif } #ifdef __WINDOWS32__ typedef void (*__code_ptr)(int); #else typedef void (*__code_ptr)(); #endif void * _CDECL stub_signal(int sig, void *handler) { #if defined(__WIN32_VXD__) || defined(__NT_DRIVER__) || defined(__SMX32__) return NULL; #else return (void*)signal(sig,(__code_ptr)handler); #endif }