Commit | Line | Data |
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 | |
12 | class CPerlLIO : public IPerlLIO |
13 | { |
14 | public: |
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; }; |
45 | protected: |
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 | |
96 | int CPerlLIO::Access(const char *path, int mode, int &err) |
97 | { |
98 | CALLFUNCRET(access(path, mode)) |
99 | } |
100 | |
101 | int CPerlLIO::Chmod(const char *filename, int pmode, int &err) |
102 | { |
103 | CALLFUNCRET(chmod(filename, pmode)) |
104 | } |
105 | |
106 | int CPerlLIO::Chsize(int handle, long size, int &err) |
107 | { |
108 | CALLFUNCRET(chsize(handle, size)) |
109 | } |
110 | |
111 | int CPerlLIO::Close(int fd, int &err) |
112 | { |
113 | CALLFUNCRET(close(fd)) |
114 | } |
115 | |
116 | int CPerlLIO::Dup(int fd, int &err) |
117 | { |
118 | CALLFUNCERR(dup(fd)) |
119 | } |
120 | |
121 | int 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 | |
134 | int 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 | |
172 | int CPerlLIO::FStat(int fd, struct stat *sbufptr, int &err) |
173 | { |
565764a8 |
174 | CALLFUNCERR(fstat(fd, sbufptr)) |
76e3520e |
175 | } |
176 | |
177 | int 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 | |
182 | int CPerlLIO::Isatty(int fd, int &err) |
183 | { |
184 | return isatty(fd); |
185 | } |
186 | |
187 | long CPerlLIO::Lseek(int fd, long offset, int origin, int &err) |
188 | { |
189 | LCALLFUNCERR(lseek(fd, offset, origin)) |
190 | } |
191 | |
192 | int CPerlLIO::Lstat(const char *path, struct stat *sbufptr, int &err) |
193 | { |
565764a8 |
194 | return STat(path, sbufptr, err); |
76e3520e |
195 | } |
196 | |
197 | char *CPerlLIO::Mktemp(char *Template, int &err) |
198 | { |
199 | return mktemp(Template); |
200 | } |
201 | |
202 | int 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 | |
215 | int 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 | |
228 | int CPerlLIO::Read(int fd, void *buffer, unsigned int cnt, int &err) |
229 | { |
230 | CALLFUNCERR(read(fd, buffer, cnt)) |
231 | } |
232 | |
233 | int 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 | |
285 | int CPerlLIO::Setmode(int fd, int mode, int &err) |
286 | { |
287 | CALLFUNCRET(setmode(fd, mode)) |
288 | } |
289 | |
290 | int 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 | |
332 | char *CPerlLIO::Tmpnam(char *string, int &err) |
333 | { |
334 | return tmpnam(string); |
335 | } |
336 | |
337 | int CPerlLIO::Umask(int pmode, int &err) |
338 | { |
339 | return umask(pmode); |
340 | } |
341 | |
342 | int CPerlLIO::Unlink(const char *filename, int &err) |
343 | { |
344 | chmod(filename, _S_IREAD | _S_IWRITE); |
345 | CALLFUNCRET(unlink(filename)) |
346 | } |
347 | |
348 | int CPerlLIO::Utime(char *filename, struct utimbuf *times, int &err) |
349 | { |
350 | CALLFUNCRET(utime(filename, times)) |
351 | } |
352 | |
353 | int CPerlLIO::Write(int fd, const void *buffer, unsigned int cnt, int &err) |
354 | { |
355 | CALLFUNCERR(write(fd, buffer, cnt)) |
356 | } |
357 | |