Mercurial > repo
comparison perl-5.22.2/win32/win32ceio.c @ 8045:a16537d2fe07
<xfix> tar xf perl-5.22.2.tar.gz # Ah, whatever, I\'m doing it anyway
author | HackBot |
---|---|
date | Sat, 14 May 2016 14:54:38 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
8044:711c038a7dce | 8045:a16537d2fe07 |
---|---|
1 #define PERL_NO_GET_CONTEXT | |
2 #define WIN32_LEAN_AND_MEAN | |
3 #define WIN32IO_IS_STDIO | |
4 #include <tchar.h> | |
5 #ifdef __GNUC__ | |
6 #define Win32_Winsock | |
7 #endif | |
8 #include <windows.h> | |
9 #include <cewin32.h> | |
10 | |
11 #include <sys/stat.h> | |
12 #include "EXTERN.h" | |
13 #include "perl.h" | |
14 | |
15 #ifdef PERLIO_LAYERS | |
16 | |
17 #include "perliol.h" | |
18 | |
19 #define NO_XSLOCKS | |
20 #include "XSUB.h" | |
21 | |
22 | |
23 /* Bottom-most level for Win32 case */ | |
24 | |
25 typedef struct | |
26 { | |
27 struct _PerlIO base; /* The generic part */ | |
28 HANDLE h; /* OS level handle */ | |
29 IV refcnt; /* REFCNT for the "fd" this represents */ | |
30 int fd; /* UNIX like file descriptor - index into fdtable */ | |
31 } PerlIOWin32; | |
32 | |
33 PerlIOWin32 *fdtable[256]; | |
34 IV max_open_fd = -1; | |
35 | |
36 IV | |
37 PerlIOWin32_popped(pTHX_ PerlIO *f) | |
38 { | |
39 PerlIOWin32 *s = PerlIOSelf(f,PerlIOWin32); | |
40 if (--s->refcnt > 0) | |
41 { | |
42 *f = PerlIOBase(f)->next; | |
43 return 1; | |
44 } | |
45 fdtable[s->fd] = NULL; | |
46 return 0; | |
47 } | |
48 | |
49 IV | |
50 PerlIOWin32_fileno(pTHX_ PerlIO *f) | |
51 { | |
52 return PerlIOSelf(f,PerlIOWin32)->fd; | |
53 } | |
54 | |
55 IV | |
56 PerlIOWin32_pushed(pTHX_ PerlIO *f, const char *mode, SV *arg, PerlIO_funcs *tab) | |
57 { | |
58 IV code = PerlIOBase_pushed(aTHX_ f,mode,arg,tab); | |
59 if (*PerlIONext(f)) | |
60 { | |
61 PerlIOWin32 *s = PerlIOSelf(f,PerlIOWin32); | |
62 s->fd = PerlIO_fileno(PerlIONext(f)); | |
63 } | |
64 PerlIOBase(f)->flags |= PERLIO_F_OPEN; | |
65 return code; | |
66 } | |
67 | |
68 PerlIO * | |
69 PerlIOWin32_open(pTHX_ PerlIO_funcs *self, PerlIO_list_t *layers, IV n, const char *mode, int fd, int imode, int perm, PerlIO *f, int narg, SV **args) | |
70 { | |
71 const char *tmode = mode; | |
72 HANDLE h = INVALID_HANDLE_VALUE; | |
73 if (f) | |
74 { | |
75 /* Close if already open */ | |
76 if (PerlIOBase(f)->flags & PERLIO_F_OPEN) | |
77 (*PerlIOBase(f)->tab->Close)(aTHX_ f); | |
78 } | |
79 if (narg > 0) | |
80 { | |
81 char *path = SvPV_nolen(*args); | |
82 DWORD access = 0; | |
83 DWORD share = 0; | |
84 DWORD create = -1; | |
85 DWORD attr = FILE_ATTRIBUTE_NORMAL; | |
86 if (*mode == '#') | |
87 { | |
88 /* sysopen - imode is UNIX-like O_RDONLY etc. | |
89 - do_open has converted that back to string form in mode as well | |
90 - perm is UNIX like permissions | |
91 */ | |
92 mode++; | |
93 } | |
94 else | |
95 { | |
96 /* Normal open - decode mode string */ | |
97 } | |
98 switch(*mode) | |
99 { | |
100 case 'r': | |
101 access = GENERIC_READ; | |
102 create = OPEN_EXISTING; | |
103 if (*++mode == '+') | |
104 { | |
105 access |= GENERIC_WRITE; | |
106 create = OPEN_ALWAYS; | |
107 mode++; | |
108 } | |
109 break; | |
110 | |
111 case 'w': | |
112 access = GENERIC_WRITE; | |
113 create = TRUNCATE_EXISTING; | |
114 if (*++mode == '+') | |
115 { | |
116 access |= GENERIC_READ; | |
117 mode++; | |
118 } | |
119 break; | |
120 | |
121 case 'a': | |
122 access = GENERIC_WRITE; | |
123 create = OPEN_ALWAYS; | |
124 if (*++mode == '+') | |
125 { | |
126 access |= GENERIC_READ; | |
127 mode++; | |
128 } | |
129 break; | |
130 } | |
131 if (*mode == 'b') | |
132 { | |
133 mode++; | |
134 } | |
135 else if (*mode == 't') | |
136 { | |
137 mode++; | |
138 } | |
139 if (*mode || create == -1) | |
140 { | |
141 //FIX-ME: SETERRNO(EINVAL,LIB$_INVARG); | |
142 XCEMessageBoxA(NULL, "NEED TO IMPLEMENT a place in ../wince/win32io.c", "Perl(developer)", 0); | |
143 return NULL; | |
144 } | |
145 if (!(access & GENERIC_WRITE)) | |
146 share = FILE_SHARE_READ; | |
147 h = CreateFileW(path,access,share,NULL,create,attr,NULL); | |
148 if (h == INVALID_HANDLE_VALUE) | |
149 { | |
150 if (create == TRUNCATE_EXISTING) | |
151 h = CreateFileW(path,access,share,NULL,(create = OPEN_ALWAYS),attr,NULL); | |
152 } | |
153 } | |
154 else | |
155 { | |
156 /* fd open */ | |
157 h = INVALID_HANDLE_VALUE; | |
158 if (fd >= 0 && fd <= max_open_fd) | |
159 { | |
160 PerlIOWin32 *s = fdtable[fd]; | |
161 if (s) | |
162 { | |
163 s->refcnt++; | |
164 if (!f) | |
165 f = PerlIO_allocate(aTHX); | |
166 *f = &s->base; | |
167 return f; | |
168 } | |
169 } | |
170 if (*mode == 'I') | |
171 { | |
172 mode++; | |
173 switch(fd) | |
174 { | |
175 case 0: | |
176 h = XCEGetStdHandle(STD_INPUT_HANDLE); | |
177 break; | |
178 case 1: | |
179 h = XCEGetStdHandle(STD_OUTPUT_HANDLE); | |
180 break; | |
181 case 2: | |
182 h = XCEGetStdHandle(STD_ERROR_HANDLE); | |
183 break; | |
184 } | |
185 } | |
186 } | |
187 if (h != INVALID_HANDLE_VALUE) | |
188 fd = win32_open_osfhandle((intptr_t) h, PerlIOUnix_oflags(tmode)); | |
189 if (fd >= 0) | |
190 { | |
191 PerlIOWin32 *s; | |
192 if (!f) | |
193 f = PerlIO_allocate(aTHX); | |
194 s = PerlIOSelf(PerlIO_push(aTHX_ f,self,tmode,PerlIOArg),PerlIOWin32); | |
195 s->h = h; | |
196 s->fd = fd; | |
197 s->refcnt = 1; | |
198 if (fd >= 0) | |
199 { | |
200 fdtable[fd] = s; | |
201 if (fd > max_open_fd) | |
202 max_open_fd = fd; | |
203 } | |
204 return f; | |
205 } | |
206 if (f) | |
207 { | |
208 /* FIXME: pop layers ??? */ | |
209 } | |
210 return NULL; | |
211 } | |
212 | |
213 SSize_t | |
214 PerlIOWin32_read(pTHX_ PerlIO *f, void *vbuf, Size_t count) | |
215 { | |
216 PerlIOWin32 *s = PerlIOSelf(f,PerlIOWin32); | |
217 DWORD len; | |
218 if (!(PerlIOBase(f)->flags & PERLIO_F_CANREAD)) | |
219 return 0; | |
220 if (ReadFile(s->h,vbuf,count,&len,NULL)) | |
221 { | |
222 return len; | |
223 } | |
224 else | |
225 { | |
226 if (GetLastError() != NO_ERROR) | |
227 { | |
228 PerlIOBase(f)->flags |= PERLIO_F_ERROR; | |
229 PerlIO_save_errno(f); | |
230 return -1; | |
231 } | |
232 else | |
233 { | |
234 if (count != 0) | |
235 PerlIOBase(f)->flags |= PERLIO_F_EOF; | |
236 return 0; | |
237 } | |
238 } | |
239 } | |
240 | |
241 SSize_t | |
242 PerlIOWin32_write(pTHX_ PerlIO *f, const void *vbuf, Size_t count) | |
243 { | |
244 PerlIOWin32 *s = PerlIOSelf(f,PerlIOWin32); | |
245 DWORD len; | |
246 if (WriteFile(s->h,vbuf,count,&len,NULL)) | |
247 { | |
248 return len; | |
249 } | |
250 else | |
251 { | |
252 PerlIOBase(f)->flags |= PERLIO_F_ERROR; | |
253 PerlIO_save_errno(f); | |
254 return -1; | |
255 } | |
256 } | |
257 | |
258 IV | |
259 PerlIOWin32_seek(pTHX_ PerlIO *f, Off_t offset, int whence) | |
260 { | |
261 static const DWORD where[3] = { FILE_BEGIN, FILE_CURRENT, FILE_END }; | |
262 PerlIOWin32 *s = PerlIOSelf(f,PerlIOWin32); | |
263 DWORD high = (sizeof(offset) > sizeof(DWORD)) ? (DWORD)(offset >> 32) : 0; | |
264 DWORD low = (DWORD) offset; | |
265 DWORD res = SetFilePointer(s->h,low,&high,where[whence]); | |
266 if (res != 0xFFFFFFFF || GetLastError() != NO_ERROR) | |
267 { | |
268 return 0; | |
269 } | |
270 else | |
271 { | |
272 return -1; | |
273 } | |
274 } | |
275 | |
276 Off_t | |
277 PerlIOWin32_tell(pTHX_ PerlIO *f) | |
278 { | |
279 PerlIOWin32 *s = PerlIOSelf(f,PerlIOWin32); | |
280 DWORD high = 0; | |
281 DWORD res = SetFilePointer(s->h,0,&high,FILE_CURRENT); | |
282 if (res != 0xFFFFFFFF || GetLastError() != NO_ERROR) | |
283 { | |
284 return ((Off_t) high << 32) | res; | |
285 } | |
286 return (Off_t) -1; | |
287 } | |
288 | |
289 IV | |
290 PerlIOWin32_close(pTHX_ PerlIO *f) | |
291 { | |
292 PerlIOWin32 *s = PerlIOSelf(f,PerlIOWin32); | |
293 if (s->refcnt == 1) | |
294 { | |
295 IV code = 0; | |
296 #if 0 | |
297 /* This does not do pipes etc. correctly */ | |
298 if (!CloseHandle(s->h)) | |
299 { | |
300 s->h = INVALID_HANDLE_VALUE; | |
301 return -1; | |
302 } | |
303 #else | |
304 PerlIOBase(f)->flags &= ~PERLIO_F_OPEN; | |
305 return win32_close(s->fd); | |
306 #endif | |
307 } | |
308 return 0; | |
309 } | |
310 | |
311 PerlIO * | |
312 PerlIOWin32_dup(pTHX_ PerlIO *f, PerlIO *o, CLONE_PARAMS *params, int flags) | |
313 { | |
314 PerlIOWin32 *os = PerlIOSelf(f,PerlIOWin32); | |
315 HANDLE proc = GetCurrentProcess(); | |
316 HANDLE new; | |
317 if (DuplicateHandle(proc, os->h, proc, &new, 0, FALSE, DUPLICATE_SAME_ACCESS)) | |
318 { | |
319 char mode[8]; | |
320 int fd = win32_open_osfhandle((intptr_t) new, PerlIOUnix_oflags(PerlIO_modestr(o,mode))); | |
321 if (fd >= 0) | |
322 { | |
323 f = PerlIOBase_dup(aTHX_ f, o, params, flags); | |
324 if (f) | |
325 { | |
326 PerlIOWin32 *fs = PerlIOSelf(f,PerlIOWin32); | |
327 fs->h = new; | |
328 fs->fd = fd; | |
329 fs->refcnt = 1; | |
330 fdtable[fd] = fs; | |
331 if (fd > max_open_fd) | |
332 max_open_fd = fd; | |
333 } | |
334 else | |
335 { | |
336 win32_close(fd); | |
337 } | |
338 } | |
339 else | |
340 { | |
341 CloseHandle(new); | |
342 } | |
343 } | |
344 return f; | |
345 } | |
346 | |
347 PerlIO_funcs PerlIO_win32 = { | |
348 sizeof(PerlIO_funcs), | |
349 "win32", | |
350 sizeof(PerlIOWin32), | |
351 PERLIO_K_RAW, | |
352 PerlIOWin32_pushed, | |
353 PerlIOWin32_popped, | |
354 PerlIOWin32_open, | |
355 PerlIOBase_binmode, | |
356 NULL, /* getarg */ | |
357 PerlIOWin32_fileno, | |
358 PerlIOWin32_dup, | |
359 PerlIOWin32_read, | |
360 PerlIOBase_unread, | |
361 PerlIOWin32_write, | |
362 PerlIOWin32_seek, | |
363 PerlIOWin32_tell, | |
364 PerlIOWin32_close, | |
365 PerlIOBase_noop_ok, /* flush */ | |
366 PerlIOBase_noop_fail, /* fill */ | |
367 PerlIOBase_eof, | |
368 PerlIOBase_error, | |
369 PerlIOBase_clearerr, | |
370 PerlIOBase_setlinebuf, | |
371 NULL, /* get_base */ | |
372 NULL, /* get_bufsiz */ | |
373 NULL, /* get_ptr */ | |
374 NULL, /* get_cnt */ | |
375 NULL, /* set_ptrcnt */ | |
376 }; | |
377 | |
378 #endif | |
379 |