1 /* 2 Title: Data structures shared between basioio.c and network.c. 3 4 Copyright (c) 2000, 2016, 2018-19 David C. J. Matthews 5 Portions of this code are derived from the original stream io 6 package copyright CUTS 1983-2000. 7 8 This library is free software; you can redistribute it and/or 9 modify it under the terms of the GNU Lesser General Public 10 License version 2.1 as published by the Free Software Foundation. 11 12 This library is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 Lesser General Public License for more details. 16 17 You should have received a copy of the GNU Lesser General Public 18 License along with this library; if not, write to the Free Software 19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 20 21 */ 22 23 #ifndef IO_INTERNAL_H 24 #define IO_INTERNAL_H 25 26 // Bits to define tests and results in poll. 27 // These are the values passed to and from ML. 28 #define POLL_BIT_IN 1 29 #define POLL_BIT_OUT 2 30 #define POLL_BIT_PRI 4 31 32 // Return values from fileKind 33 #define FILEKIND_FILE 0 34 #define FILEKIND_DIR 1 35 #define FILEKIND_LINK 2 36 #define FILEKIND_TTY 3 37 #define FILEKIND_PIPE 4 38 #define FILEKIND_SKT 5 39 #define FILEKIND_DEV 6 40 #define FILEKIND_UNKNOWN 7 41 #define FILEKIND_ERROR (-1) 42 43 44 #if (defined(_WIN32)) 45 46 #include <WinSock2.h> 47 #include "locking.h" // For PLock 48 49 // Unlike Unix where select and poll can be used on both sockets and other 50 // streams, in Windows there is no single way of testing different sorts of 51 // streams. 52 class WinStreamBase 53 { 54 public: ~WinStreamBase()55 virtual ~WinStreamBase() {} // Quieten some warnings pollTest()56 virtual int pollTest() { // Return the valid options for this descriptor 57 return 0; 58 } poll(TaskData * taskData,int test)59 virtual int poll(TaskData *taskData, int test) { // Return the values set 60 return 0; 61 } 62 // These are not currently used but could be used to poll 63 // multiple sockets or streams. getSocket()64 virtual SOCKET getSocket() { 65 return INVALID_SOCKET; 66 } getHandle()67 virtual HANDLE getHandle() { 68 return INVALID_HANDLE_VALUE; 69 } 70 }; 71 72 typedef enum { OPENREAD, OPENWRITE, OPENAPPEND } openMode; 73 74 // Abstract Windows stream 75 class WinStream : public WinStreamBase 76 { 77 public: 78 virtual void closeEntry(TaskData *taskData) = 0; 79 80 // Block for a short time until either input is possible, returning true, 81 // or the time-out, which may be zero, has expired. 82 virtual bool testForInput(TaskData *taskData, unsigned waitMilliSecs) = 0; 83 84 // The same for output. 85 virtual bool testForOutput(TaskData *taskData, unsigned waitMilliSecs) = 0; 86 87 // These are really for backwards compatibility. 88 virtual void waitUntilAvailable(TaskData *taskData); 89 virtual void waitUntilOutputPossible(TaskData *taskData); 90 readStream(TaskData * taskData,byte * base,size_t length)91 virtual size_t readStream(TaskData *taskData, byte *base, size_t length) { 92 unimplemented(taskData); 93 return 0; 94 } getPos(TaskData * taskData)95 virtual uint64_t getPos(TaskData *taskData) { 96 unimplemented(taskData); 97 return 0; 98 } setPos(TaskData * taskData,uint64_t pos)99 virtual void setPos(TaskData *taskData, uint64_t pos) { 100 unimplemented(taskData); 101 } fileSize(TaskData * taskData)102 virtual uint64_t fileSize(TaskData *taskData) { 103 unimplemented(taskData); 104 return 0; 105 } writeStream(TaskData * taskData,byte * base,size_t length)106 virtual size_t writeStream(TaskData *taskData, byte *base, size_t length) { 107 unimplemented(taskData); 108 return 0; 109 } 110 virtual int fileKind() = 0; 111 static int fileTypeOfHandle(HANDLE hStream); 112 113 protected: 114 void unimplemented(TaskData *taskData); 115 }; 116 117 // Windows stream input using overlapped IO and the Windows calls. 118 class WinInOutStream : public WinStream 119 { 120 public: 121 WinInOutStream(); 122 ~WinInOutStream(); 123 virtual void closeEntry(TaskData *taskData); 124 virtual void openFile(TaskData * taskData, TCHAR *name, openMode mode, bool text); 125 virtual size_t readStream(TaskData *taskData, byte *base, size_t length); 126 127 virtual bool testForInput(TaskData *taskData, unsigned waitMilliSecs); 128 virtual bool testForOutput(TaskData *taskData, unsigned waitMilliSecs); 129 130 virtual uint64_t getPos(TaskData *taskData); 131 virtual void setPos(TaskData *taskData, uint64_t pos); 132 virtual uint64_t fileSize(TaskData *taskData); 133 134 virtual size_t writeStream(TaskData *taskData, byte *base, size_t length); 135 136 // Open on a handle. This returns an error result rather than raising an exception 137 virtual bool openHandle(HANDLE hndl, openMode mode, bool isText); 138 fileKind()139 virtual int fileKind() { 140 return WinStream::fileTypeOfHandle(hStream); 141 } 142 pollTest()143 virtual int pollTest() { 144 // We can poll this to test for input. 145 return isRead ? POLL_BIT_IN : POLL_BIT_OUT; 146 } 147 148 virtual int poll(TaskData *taskData, int test); 149 getHandle()150 virtual HANDLE getHandle() { 151 return hEvent; 152 } 153 154 protected: 155 bool beginReading(); 156 void flushOut(TaskData *taskData); getOverlappedPos()157 uint64_t getOverlappedPos() { 158 return ((uint64_t)(overlap.OffsetHigh) << 32) + overlap.Offset; 159 } setOverlappedPos(uint64_t newPos)160 void setOverlappedPos(uint64_t newPos) { 161 overlap.Offset = (DWORD)newPos; 162 overlap.OffsetHigh = (DWORD)(newPos >> 32); 163 } 164 165 bool isAvailable(TaskData *taskData); 166 bool canOutput(TaskData *taskData); 167 168 protected: 169 bool isRead; 170 bool isText; // Remove CRs? 171 byte *buffer; 172 unsigned buffSize, currentInBuffer, currentPtr; 173 bool endOfStream; 174 HANDLE hStream; 175 HANDLE hEvent; 176 OVERLAPPED overlap; 177 PLock lock; 178 }; 179 180 // Create a new pipe. 181 extern void newPipeName(TCHAR *name); 182 183 #else 184 185 extern Handle wrapFileDescriptor(TaskData *taskData, int fd); 186 // Get a file descriptor and raise an exception if it is closed. 187 extern int getStreamFileDescriptor(TaskData *taskData, PolyWord strm); 188 extern int getStreamFileDescriptorWithoutCheck(PolyWord strm); 189 190 #endif 191 192 // This is used in both basicio and unix-specific 193 #if defined(HAVE_STRUCT_STAT_ST_ATIM) 194 # define STAT_SECS(stat,kind) (stat)->st_##kind##tim.tv_sec 195 # define STAT_USECS(stat,kind) (((stat)->st_##kind##tim.tv_nsec + 500) / 1000) 196 #elif defined(HAVE_STRUCT_STAT_ST_ATIMENSEC) 197 # define STAT_SECS(stat,kind) (stat)->st_##kind##time 198 # define STAT_USECS(stat,kind) (((stat)->st_##kind##timensec + 500) / 1000) 199 #elif defined(HAVE_STRUCT_STAT_ST_ATIMESPEC) 200 # define STAT_SECS(stat,kind) (stat)->st_##kind##timespec.tv_sec 201 # define STAT_USECS(stat,kind) (((stat)->st_##kind##timespec.tv_nsec + 500) / 1000) 202 #elif defined(HAVE_STRUCT_STAT_ST_ATIME_N) 203 # define STAT_SECS(stat,kind) (stat)->st_##kind##time 204 # define STAT_USECS(stat,kind) (((stat)->st_##kind##time_n + 500) / 1000) 205 #elif defined(HAVE_STRUCT_STAT_ST_UATIME) 206 # define STAT_SECS(stat,kind) (stat)->st_##kind##time 207 # define STAT_USECS(stat,kind) (stat)->st_u##kind##time 208 #else 209 # define STAT_SECS(stat,kind) (stat)->st_##kind##time 210 # define STAT_USECS(stat,kind) 0 211 #endif 212 213 #endif 214