[asperl] added AS patch#2
[p5sagit/p5-mst-13.2.git] / win32 / iplio.c
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 {
174         int ret = fstat(fd, sbufptr);
175         if(errno)
176                 err = errno;
177         return ret;
178 }
179
180 int CPerlLIO::IOCtl(int i, unsigned int u, char *data, int &err)
181 {
182         return pSock->IoctlSocket((SOCKET)i, (long)u, (u_long*)data, err);
183 }
184
185 int CPerlLIO::Isatty(int fd, int &err)
186 {
187         return isatty(fd);
188 }
189
190 long CPerlLIO::Lseek(int fd, long offset, int origin, int &err)
191 {
192         LCALLFUNCERR(lseek(fd, offset, origin))
193 }
194
195 int CPerlLIO::Lstat(const char *path, struct stat *sbufptr, int &err)
196 {
197         return stat(path, sbufptr);
198 }
199
200 char *CPerlLIO::Mktemp(char *Template, int &err)
201 {
202         return mktemp(Template);
203 }
204
205 int CPerlLIO::Open(const char *filename, int oflag, int &err)
206 {
207         CALLFUNCERR(open(filename, oflag))
208 }
209
210 int CPerlLIO::Open(const char *filename, int oflag, int pmode, int &err)
211 {
212         CALLFUNCERR(open(filename, oflag, pmode))
213 }
214
215 int CPerlLIO::Read(int fd, void *buffer, unsigned int cnt, int &err)
216 {
217         CALLFUNCERR(read(fd, buffer, cnt))
218 }
219
220 int CPerlLIO::Rename(const char *OldFileName, const char *newname, int &err)
221 {
222         char szNewWorkName[MAX_PATH+1];
223         WIN32_FIND_DATA fdOldFile, fdNewFile;
224         HANDLE handle;
225         char *ptr;
226
227         if((strchr(OldFileName, '\\') || strchr(OldFileName, '/'))
228                 && strchr(newname, '\\') == NULL
229                         && strchr(newname, '/') == NULL)
230         {
231                 strcpy(szNewWorkName, OldFileName);
232                 if((ptr = strrchr(szNewWorkName, '\\')) == NULL)
233                         ptr = strrchr(szNewWorkName, '/');
234                 strcpy(++ptr, newname);
235         }
236         else
237                 strcpy(szNewWorkName, newname);
238
239         if(stricmp(OldFileName, szNewWorkName) != 0)
240         {   // check that we're not being fooled by relative paths
241                 // and only delete the new file
242                 //  1) if it exists
243                 //  2) it is not the same file as the old file
244                 //  3) old file exist
245                 // GetFullPathName does not return the long file name on some systems
246                 handle = FindFirstFile(OldFileName, &fdOldFile);
247                 if(handle != INVALID_HANDLE_VALUE)
248                 {
249                         FindClose(handle);
250         
251                         handle = FindFirstFile(szNewWorkName, &fdNewFile);
252         
253                         if(handle != INVALID_HANDLE_VALUE)
254                                 FindClose(handle);
255                         else
256                                 fdNewFile.cFileName[0] = '\0';
257
258                         if(strcmp(fdOldFile.cAlternateFileName, fdNewFile.cAlternateFileName) != 0
259                                 && strcmp(fdOldFile.cFileName, fdNewFile.cFileName) != 0)
260                         {   // file exists and not same file
261                                 DeleteFile(szNewWorkName);
262                         }
263                 }
264         }
265         int ret = rename(OldFileName, szNewWorkName);
266         if(ret)
267                 err = errno;
268
269         return ret;
270 }
271
272 int CPerlLIO::Setmode(int fd, int mode, int &err)
273 {
274         CALLFUNCRET(setmode(fd, mode))
275 }
276
277 int CPerlLIO::STat(const char *path, struct stat *sbufptr, int &err)
278 {
279         return stat(path, sbufptr);
280 }
281
282 char *CPerlLIO::Tmpnam(char *string, int &err)
283 {
284         return tmpnam(string);
285 }
286
287 int CPerlLIO::Umask(int pmode, int &err)
288 {
289         return umask(pmode);
290 }
291
292 int CPerlLIO::Unlink(const char *filename, int &err)
293 {
294         chmod(filename, _S_IREAD | _S_IWRITE);
295         CALLFUNCRET(unlink(filename))
296 }
297
298 int CPerlLIO::Utime(char *filename, struct utimbuf *times, int &err)
299 {
300         CALLFUNCRET(utime(filename, times))
301 }
302
303 int CPerlLIO::Write(int fd, const void *buffer, unsigned int cnt, int &err)
304 {
305         CALLFUNCERR(write(fd, buffer, cnt))
306 }
307