source: trunk/source/lisp-kernel/windows-calls.c @ 10564

Last change on this file since 10564 was 10564, checked in by gb, 12 years ago

New file, from branches/win64.

File size: 9.0 KB
Line 
1/*
2   Copyright (C) 2008, Clozure Associates and contributors,
3   This file is part of Clozure CL. 
4
5   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
6   License , known as the LLGPL and distributed with Clozure CL as the
7   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
8   which is distributed with Clozure CL as the file "LGPL".  Where these
9   conflict, the preamble takes precedence. 
10
11   Clozure CL is referenced in the preamble as the "LIBRARY."
12
13   The LLGPL is also available online at
14   http://opensource.franz.com/preamble.html
15*/
16
17/*
18   These aren't really system calls; they're just C runtime functions
19   that (a) are built in to the lisp, so they can be called early
20   in the cold load, before the FFI is initialized and (b) return negated
21   error code on failure, so that it's not necessary to separately
22   fetch errno.
23
24   It's reasonable to consider replacing these things with wrappers
25   around native functionality (ReadFile, etc.) someday.
26
27   The order of the entries in windows_syscall_table[] should match
28   the order of syscall indices defined in
29   "ccl:library;x86-win64-syscalls.lisp".
30
31   One last time: these aren't really system calls.
32*/
33
34#include "lisp.h"
35#include "x86-exceptions.h"
36#include <io.h>
37#include <unistd.h>
38#include <sys/fcntl.h>
39#include <errno.h>
40#include <sys/stat.h>
41#include <windows.h>
42#include <psapi.h>
43#include <dirent.h>
44#include <stdio.h>
45
46
47
48#define _dosmaperr mingw_dosmaperr
49
50
51#define WSYSCALL_RETURN(form) \
52  do { \
53    int __result = form; \
54\
55    if (__result < 0){ \
56      return -errno; \
57    } \
58    return __result; \
59  } while (0)
60
61
62
63__int64
64windows_open(wchar_t *path, int flag, int mode)
65{
66  int fd;
67  HANDLE hfile;
68  DWORD dwDesiredAccess = 0;
69  DWORD dwShareMode = 0;
70  DWORD dwCreationDistribution = 0;
71  DWORD dwFlagsAndAttributes = 0;
72  SECURITY_ATTRIBUTES sa = {sizeof(SECURITY_ATTRIBUTES), NULL, TRUE};
73
74  if ((flag & S_IREAD) == S_IREAD) {
75    dwShareMode = FILE_SHARE_READ;
76  } else {
77    if ((flag & S_IWRITE) == S_IWRITE) {
78      dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
79    }
80  }
81
82  if ((flag & _O_WRONLY) == _O_WRONLY) {
83    dwDesiredAccess |= GENERIC_WRITE | FILE_WRITE_DATA |
84      FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES;
85  } else if ((flag & _O_RDWR) == _O_RDWR) {
86    dwDesiredAccess |= GENERIC_WRITE|GENERIC_READ | FILE_READ_DATA |
87      FILE_WRITE_DATA | FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES;
88  } else {
89    dwDesiredAccess |= GENERIC_READ | FILE_READ_DATA | FILE_READ_ATTRIBUTES |
90      FILE_WRITE_ATTRIBUTES;
91  }
92   
93  if ((flag & S_IREAD) == S_IREAD) {
94    dwShareMode |= FILE_SHARE_READ;
95  }
96  if ((flag & S_IWRITE) == S_IWRITE) {
97    dwShareMode |= FILE_SHARE_WRITE;
98  }
99
100  if ((flag & (_O_CREAT | _O_EXCL)) == (_O_CREAT | _O_EXCL)) {
101    dwCreationDistribution |= CREATE_NEW;
102  } else if ((flag &  O_TRUNC) == O_TRUNC) {
103    if ((flag &  O_CREAT) ==  O_CREAT) {
104      dwCreationDistribution |= CREATE_ALWAYS;
105    } else if ((flag & O_RDONLY) != O_RDONLY) {
106      dwCreationDistribution |= TRUNCATE_EXISTING;
107    }
108  } else if ((flag & _O_APPEND) == _O_APPEND) {
109    dwCreationDistribution |= OPEN_EXISTING;
110  } else if ((flag &  _O_CREAT) == _O_CREAT) {
111    dwCreationDistribution |= OPEN_ALWAYS;
112  } else {
113    dwCreationDistribution |= OPEN_EXISTING;
114  }
115  if ((flag &  _O_RANDOM) == _O_RANDOM) {
116    dwFlagsAndAttributes |= FILE_FLAG_RANDOM_ACCESS;
117  }
118  if ((flag &  _O_SEQUENTIAL) == _O_SEQUENTIAL) {
119    dwFlagsAndAttributes |= FILE_FLAG_SEQUENTIAL_SCAN;
120  }
121
122  if ((flag &  _O_TEMPORARY) == _O_TEMPORARY) {
123    dwFlagsAndAttributes |= FILE_FLAG_DELETE_ON_CLOSE;
124  }
125
126  if ((flag &  _O_SHORT_LIVED) == _O_SHORT_LIVED) {
127    dwFlagsAndAttributes |= FILE_FLAG_DELETE_ON_CLOSE;
128  }
129
130  if (flag & _O_NOINHERIT) {
131    sa.bInheritHandle = FALSE;
132  }
133
134#if 0
135  dwFlagsAndAttributes |= FILE_FLAG_OVERLAPPED;
136#endif
137   
138
139  hfile = CreateFileW(path,
140                      dwDesiredAccess,
141                      dwShareMode,
142                      &sa,
143                      dwCreationDistribution,
144                      dwFlagsAndAttributes,
145                      NULL);
146  if (hfile == ((HANDLE)-1)) {
147    _dosmaperr(GetLastError());
148    return -errno;
149  }
150  fd = _open_osfhandle((intptr_t)hfile, flag);
151
152  if (fd < 0) {
153    CloseHandle(hfile);
154  }
155  return fd;
156}
157
158__int64
159windows_close(int fd)
160{
161  WSYSCALL_RETURN(close(fd));
162}
163
164__int64
165windows_read(int fd, void *buf, unsigned int count)
166{
167  HANDLE hfile;
168  OVERLAPPED overlapped;
169  DWORD err, nread;
170  pending_io pending;
171  TCR *tcr;
172  extern TCR *get_tcr(int);
173
174  hfile = (HANDLE) _get_osfhandle(fd);
175
176  if (hfile == ((HANDLE)-1)) {
177    return -EBADF;
178  }
179 
180  memset(&overlapped,0,sizeof(overlapped));
181
182  if (GetFileType(hfile) == FILE_TYPE_DISK) {
183    overlapped.Offset = SetFilePointer(hfile, 0, &(overlapped.OffsetHigh), FILE_CURRENT);
184  }
185
186  tcr = (TCR *)get_tcr(1);
187  pending.h = hfile;
188  pending.o = &overlapped;
189  tcr->foreign_exception_status = (signed_natural)&pending;
190
191  if (ReadFile(hfile, buf, count, &nread, &overlapped)) {
192    tcr->foreign_exception_status = 0;
193    return nread;
194  }
195  err = GetLastError();
196
197  if (err == ERROR_HANDLE_EOF) {
198    tcr->foreign_exception_status = 0;
199    return 0;
200  }
201
202  if (err != ERROR_IO_PENDING) {
203    _dosmaperr(err);
204    tcr->foreign_exception_status = 0;
205    return -errno;
206  }
207 
208  /* We block here */
209  if (GetOverlappedResult(hfile, &overlapped, &nread, TRUE)) {
210    tcr->foreign_exception_status = 0;
211    return nread;
212  }
213  err = GetLastError();
214  tcr->foreign_exception_status = 0;
215
216  switch (err) {
217  case ERROR_HANDLE_EOF: 
218    return 0;
219  case ERROR_OPERATION_ABORTED: 
220    return -EINTR;
221  default:
222    _dosmaperr(err);
223    return -errno;
224  }
225}
226
227__int64
228windows_write(int fd, void *buf, unsigned int count)
229{
230  WSYSCALL_RETURN( _write(fd, buf, count));
231}
232
233__int64
234windows_fchmod(int fd, int mode)
235{
236  return -ENOSYS;
237}
238
239__int64
240windows_lseek(int fd, _off64_t offset, int whence)
241{
242  WSYSCALL_RETURN(lseek64(fd, offset, whence));
243}
244
245__int64
246windows_stat(wchar_t *path, struct _stat64 *buf)
247{
248  WSYSCALL_RETURN(_wstat64(path,buf));
249}
250
251__int64
252windows_fstat(int fd, struct _stat64 *buf)
253{
254  WSYSCALL_RETURN(_fstat64(fd,buf));
255}
256
257
258__int64
259windows_ftruncate(int fd, _off64_t new_size)
260{
261  /* Note that _ftruncate only allows 32-bit length */
262  WSYSCALL_RETURN(ftruncate(fd,(off_t)new_size));
263}
264
265_WDIR *
266windows_opendir(wchar_t *path)
267{
268  return _wopendir(path);
269}
270
271struct _wdirent *
272windows_readdir(_WDIR *dir)
273{
274  return _wreaddir(dir);
275}
276
277__int64
278windows_closedir(_WDIR *dir)
279{
280  WSYSCALL_RETURN(_wclosedir(dir));
281}
282
283__int64
284windows_pipe(int fd[2])
285{
286  HANDLE input, output;
287  SECURITY_ATTRIBUTES sa;
288
289  sa.nLength= sizeof(SECURITY_ATTRIBUTES);
290  sa.lpSecurityDescriptor = NULL;
291  sa.bInheritHandle = TRUE;
292
293  if (!CreatePipe(&input, &output, &sa, 0))
294    {
295      wperror("CreatePipe");
296      return -1;
297    }
298  fd[0] = _open_osfhandle((intptr_t)input, 0);
299  fd[1] = _open_osfhandle((intptr_t)output, 0);
300  return 0;
301}
302
303void *
304windows_syscall_table[] = {
305  windows_open,
306  windows_close,
307  windows_read,
308  windows_write,
309  windows_fchmod,
310  windows_lseek,
311  windows_stat,
312  windows_fstat,
313  windows_ftruncate,
314  windows_opendir,
315  windows_readdir,
316  windows_closedir,
317  windows_pipe
318};
319
320HMODULE *modules = NULL;
321DWORD cbmodules = 0;
322
323void *
324windows_find_symbol(void *handle, char *name)
325{
326  if (handle == ((void *)-2L)) {
327    handle = NULL;
328  }
329  if (handle != NULL) {
330    return GetProcAddress(handle, name);
331  } else {
332    DWORD cbneeded,  have, i;
333
334    if (cbmodules == 0) {
335      cbmodules = 16 * sizeof(HANDLE);
336      modules = LocalAlloc(LPTR, cbmodules);
337    }
338   
339    while (1) {
340      EnumProcessModules(GetCurrentProcess(),modules,cbmodules,&cbneeded);
341      if (cbmodules >= cbneeded) {
342        break;
343      }
344      cbmodules = cbneeded;
345      modules = LocalReAlloc(modules,cbmodules,0);
346    }
347    have = cbneeded/sizeof(HANDLE);
348
349    for (i = 0; i < have; i++) {
350      void *addr = GetProcAddress(modules[i],name);
351
352      if (addr) {
353        return addr;
354      }
355    }
356    return NULL;
357  }
358}
359
360void
361init_windows_io()
362{
363#if 0
364  int fd;
365  HANDLE hfile0, hfile1;
366
367  hfile0 = (HANDLE) _get_osfhandle(0);
368  hfile1 = ReOpenFile(hfile0,GENERIC_READ,FILE_SHARE_READ,FILE_FLAG_OVERLAPPED);
369  if (hfile1 != ((HANDLE)-1)) {
370    fd = _open_osfhandle(hfile1,O_RDONLY);
371    dup2(fd,0);
372    _close(fd);
373    SetStdHandle(STD_INPUT_HANDLE,hfile1);
374    CloseHandle(hfile0);
375  } else {
376    wperror("ReOpenFile");
377  }
378
379  hfile0 = (HANDLE) _get_osfhandle(1);
380  hfile1 = ReOpenFile(hfile0,GENERIC_WRITE,FILE_SHARE_WRITE,FILE_FLAG_OVERLAPPED);
381  if (hfile1 != ((HANDLE)-1)) {
382    fd = _open_osfhandle(hfile1,O_WRONLY);
383    dup2(fd,1);
384    _close(fd);
385    SetStdHandle(STD_OUTPUT_HANDLE,hfile1);
386    CloseHandle(hfile0);
387  }
388
389  hfile0 = (HANDLE) _get_osfhandle(2);
390  hfile1 = ReOpenFile(hfile0,GENERIC_WRITE,FILE_SHARE_WRITE,FILE_FLAG_OVERLAPPED);
391  if (hfile1 != ((HANDLE)-1)) {
392    fd = _open_osfhandle(hfile1,O_WRONLY);
393    dup2(fd,2);
394    _close(fd);
395    SetStdHandle(STD_ERROR_HANDLE,hfile1);
396    CloseHandle(hfile0);
397  }
398#endif 
399}
400
401void
402init_winsock()
403{
404  WSADATA data;
405
406  WSAStartup((2<<8)|2,&data);
407}
Note: See TracBrowser for help on using the repository browser.