[asperl] integrate latest win32 branch
[p5sagit/p5-mst-13.2.git] / win32 / iplio.c
CommitLineData
76e3520e 1/*
2
3 iplio.c
4 Interface for perl Low IO functions
5
6*/
7
8#include <iplio.h>
9#include <sys/utime.h>
10
11
12class CPerlLIO : public IPerlLIO
13{
14public:
15 CPerlLIO() { w32_platform = (-1); pPerl = NULL; pSock = NULL; pStdIO = NULL; };
16
17 virtual int Access(const char *path, int mode, int &err);
18 virtual int Chmod(const char *filename, int pmode, int &err);
19 virtual int Chsize(int handle, long size, int &err);
20 virtual int Close(int handle, int &err);
21 virtual int Dup(int handle, int &err);
22 virtual int Dup2(int handle1, int handle2, int &err);
23 virtual int Flock(int fd, int oper, int &err);
24 virtual int FStat(int handle, struct stat *buffer, int &err);
25 virtual int IOCtl(int i, unsigned int u, char *data, int &err);
26 virtual int Isatty(int handle, int &err);
27 virtual long Lseek(int handle, long offset, int origin, int &err);
28 virtual int Lstat(const char *path, struct stat *buffer, int &err);
29 virtual char *Mktemp(char *Template, int &err);
30 virtual int Open(const char *filename, int oflag, int &err);
31 virtual int Open(const char *filename, int oflag, int pmode, int &err);
32 virtual int Read(int handle, void *buffer, unsigned int count, int &err);
33 virtual int Rename(const char *oldname, const char *newname, int &err);
34 virtual int Setmode(int handle, int mode, int &err);
35 virtual int STat(const char *path, struct stat *buffer, int &err);
36 virtual char *Tmpnam(char *string, int &err);
37 virtual int Umask(int pmode, int &err);
38 virtual int Unlink(const char *filename, int &err);
39 virtual int Utime(char *filename, struct utimbuf *times, int &err);
40 virtual int Write(int handle, const void *buffer, unsigned int count, int &err);
41
42 inline void SetPerlObj(CPerlObj *p) { pPerl = p; };
43 inline void SetSockCtl(CPerlSock *p) { pSock = p; };
44 inline void SetStdObj(IPerlStdIOWin *p) { pStdIO = p; };
45protected:
46 inline int IsWin95(void)
47 {
48 return (os_id() == VER_PLATFORM_WIN32_WINDOWS);
49 };
50 inline int IsWinNT(void)
51 {
52 return (os_id() == VER_PLATFORM_WIN32_NT);
53 };
54 int GetOSfhandle(int filenum)
55 {
56 return pStdIO->GetOSfhandle(filenum);
57 };
58 DWORD os_id(void)
59 {
60 if((-1) == w32_platform)
61 {
62 OSVERSIONINFO osver;
63
64 memset(&osver, 0, sizeof(OSVERSIONINFO));
65 osver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
66 GetVersionEx(&osver);
67 w32_platform = osver.dwPlatformId;
68 }
69 return (w32_platform);
70 }
71
72 DWORD w32_platform;
73 CPerlObj *pPerl;
74 CPerlSock *pSock;
75 IPerlStdIOWin *pStdIO;
76};
77
78#define CALLFUNCRET(x)\
79 int ret = x;\
80 if(ret)\
81 err = errno;\
82 return ret;
83
84#define CALLFUNCERR(x)\
85 int ret = x;\
86 if(errno)\
87 err = errno;\
88 return ret;
89
90#define LCALLFUNCERR(x)\
91 long ret = x;\
92 if(errno)\
93 err = errno;\
94 return ret;
95
96int CPerlLIO::Access(const char *path, int mode, int &err)
97{
98 CALLFUNCRET(access(path, mode))
99}
100
101int CPerlLIO::Chmod(const char *filename, int pmode, int &err)
102{
103 CALLFUNCRET(chmod(filename, pmode))
104}
105
106int CPerlLIO::Chsize(int handle, long size, int &err)
107{
108 CALLFUNCRET(chsize(handle, size))
109}
110
111int CPerlLIO::Close(int fd, int &err)
112{
113 CALLFUNCRET(close(fd))
114}
115
116int CPerlLIO::Dup(int fd, int &err)
117{
118 CALLFUNCERR(dup(fd))
119}
120
121int CPerlLIO::Dup2(int handle1, int handle2, int &err)
122{
123 CALLFUNCERR(dup2(handle1, handle2))
124}
125
126
127#define LK_ERR(f,i) ((f) ? (i = 0) : (err = GetLastError()))
128#define LK_LEN 0xffff0000
129#define LOCK_SH 1
130#define LOCK_EX 2
131#define LOCK_NB 4
132#define LOCK_UN 8
133
134int CPerlLIO::Flock(int fd, int oper, int &err)
135{
136 OVERLAPPED o;
137 int i = -1;
138 HANDLE fh;
139
140 if (!IsWinNT()) {
141 croak("flock() unimplemented on this platform");
142 return -1;
143 }
144 fh = (HANDLE)GetOSfhandle(fd);
145 memset(&o, 0, sizeof(o));
146
147 switch(oper) {
148 case LOCK_SH: /* shared lock */
149 LK_ERR(LockFileEx(fh, 0, 0, LK_LEN, 0, &o),i);
150 break;
151 case LOCK_EX: /* exclusive lock */
152 LK_ERR(LockFileEx(fh, LOCKFILE_EXCLUSIVE_LOCK, 0, LK_LEN, 0, &o),i);
153 break;
154 case LOCK_SH|LOCK_NB: /* non-blocking shared lock */
155 LK_ERR(LockFileEx(fh, LOCKFILE_FAIL_IMMEDIATELY, 0, LK_LEN, 0, &o),i);
156 break;
157 case LOCK_EX|LOCK_NB: /* non-blocking exclusive lock */
158 LK_ERR(LockFileEx(fh,
159 LOCKFILE_EXCLUSIVE_LOCK|LOCKFILE_FAIL_IMMEDIATELY,
160 0, LK_LEN, 0, &o),i);
161 break;
162 case LOCK_UN: /* unlock lock */
163 LK_ERR(UnlockFileEx(fh, 0, LK_LEN, 0, &o),i);
164 break;
165 default: /* unknown */
166 err = EINVAL;
167 break;
168 }
169 return i;
170}
171
172int CPerlLIO::FStat(int fd, struct stat *sbufptr, int &err)
173{
565764a8 174 CALLFUNCERR(fstat(fd, sbufptr))
76e3520e 175}
176
177int CPerlLIO::IOCtl(int i, unsigned int u, char *data, int &err)
178{
179 return pSock->IoctlSocket((SOCKET)i, (long)u, (u_long*)data, err);
180}
181
182int CPerlLIO::Isatty(int fd, int &err)
183{
184 return isatty(fd);
185}
186
187long CPerlLIO::Lseek(int fd, long offset, int origin, int &err)
188{
189 LCALLFUNCERR(lseek(fd, offset, origin))
190}
191
192int CPerlLIO::Lstat(const char *path, struct stat *sbufptr, int &err)
193{
565764a8 194 return STat(path, sbufptr, err);
76e3520e 195}
196
197char *CPerlLIO::Mktemp(char *Template, int &err)
198{
199 return mktemp(Template);
200}
201
202int CPerlLIO::Open(const char *filename, int oflag, int &err)
203{
565764a8 204 int ret;
205 if(stricmp(filename, "/dev/null") == 0)
206 ret = open("NUL", oflag);
207 else
208 ret = open(filename, oflag);
209
210 if(errno)
211 err = errno;
212 return ret;
76e3520e 213}
214
215int CPerlLIO::Open(const char *filename, int oflag, int pmode, int &err)
216{
565764a8 217 int ret;
218 if(stricmp(filename, "/dev/null") == 0)
219 ret = open("NUL", oflag, pmode);
220 else
221 ret = open(filename, oflag, pmode);
222
223 if(errno)
224 err = errno;
225 return ret;
76e3520e 226}
227
228int CPerlLIO::Read(int fd, void *buffer, unsigned int cnt, int &err)
229{
230 CALLFUNCERR(read(fd, buffer, cnt))
231}
232
233int CPerlLIO::Rename(const char *OldFileName, const char *newname, int &err)
234{
235 char szNewWorkName[MAX_PATH+1];
236 WIN32_FIND_DATA fdOldFile, fdNewFile;
237 HANDLE handle;
238 char *ptr;
239
240 if((strchr(OldFileName, '\\') || strchr(OldFileName, '/'))
241 && strchr(newname, '\\') == NULL
242 && strchr(newname, '/') == NULL)
243 {
244 strcpy(szNewWorkName, OldFileName);
245 if((ptr = strrchr(szNewWorkName, '\\')) == NULL)
246 ptr = strrchr(szNewWorkName, '/');
247 strcpy(++ptr, newname);
248 }
249 else
250 strcpy(szNewWorkName, newname);
251
252 if(stricmp(OldFileName, szNewWorkName) != 0)
253 { // check that we're not being fooled by relative paths
254 // and only delete the new file
255 // 1) if it exists
256 // 2) it is not the same file as the old file
257 // 3) old file exist
258 // GetFullPathName does not return the long file name on some systems
259 handle = FindFirstFile(OldFileName, &fdOldFile);
260 if(handle != INVALID_HANDLE_VALUE)
261 {
262 FindClose(handle);
263
264 handle = FindFirstFile(szNewWorkName, &fdNewFile);
265
266 if(handle != INVALID_HANDLE_VALUE)
267 FindClose(handle);
268 else
269 fdNewFile.cFileName[0] = '\0';
270
271 if(strcmp(fdOldFile.cAlternateFileName, fdNewFile.cAlternateFileName) != 0
272 && strcmp(fdOldFile.cFileName, fdNewFile.cFileName) != 0)
273 { // file exists and not same file
274 DeleteFile(szNewWorkName);
275 }
276 }
277 }
278 int ret = rename(OldFileName, szNewWorkName);
279 if(ret)
280 err = errno;
281
282 return ret;
283}
284
285int CPerlLIO::Setmode(int fd, int mode, int &err)
286{
287 CALLFUNCRET(setmode(fd, mode))
288}
289
290int CPerlLIO::STat(const char *path, struct stat *sbufptr, int &err)
291{
565764a8 292 char t[MAX_PATH];
293 const char *p = path;
294 int l = strlen(path);
295 int res;
296
297 if (l > 1) {
298 switch(path[l - 1]) {
299 case '\\':
300 case '/':
301 if (path[l - 2] != ':') {
302 strncpy(t, path, l - 1);
303 t[l - 1] = 0;
304 p = t;
305 };
306 }
307 }
308 res = stat(path, sbufptr);
309#ifdef __BORLANDC__
310 if (res == 0) {
311 if (S_ISDIR(buffer->st_mode))
312 buffer->st_mode |= S_IWRITE | S_IEXEC;
313 else if (S_ISREG(buffer->st_mode)) {
314 if (l >= 4 && path[l-4] == '.') {
315 const char *e = path + l - 3;
316 if (strnicmp(e,"exe",3)
317 && strnicmp(e,"bat",3)
318 && strnicmp(e,"com",3)
319 && (IsWin95() || strnicmp(e,"cmd",3)))
320 buffer->st_mode &= ~S_IEXEC;
321 else
322 buffer->st_mode |= S_IEXEC;
323 }
324 else
325 buffer->st_mode &= ~S_IEXEC;
326 }
327 }
328#endif
329 return res;
76e3520e 330}
331
332char *CPerlLIO::Tmpnam(char *string, int &err)
333{
334 return tmpnam(string);
335}
336
337int CPerlLIO::Umask(int pmode, int &err)
338{
339 return umask(pmode);
340}
341
342int CPerlLIO::Unlink(const char *filename, int &err)
343{
344 chmod(filename, _S_IREAD | _S_IWRITE);
345 CALLFUNCRET(unlink(filename))
346}
347
348int CPerlLIO::Utime(char *filename, struct utimbuf *times, int &err)
349{
350 CALLFUNCRET(utime(filename, times))
351}
352
353int CPerlLIO::Write(int fd, const void *buffer, unsigned int cnt, int &err)
354{
355 CALLFUNCERR(write(fd, buffer, cnt))
356}
357