Changeset 11085


Ignore:
Timestamp:
Oct 14, 2008, 2:13:26 AM (11 years ago)
Author:
gb
Message:

Accept native windows file handles as well as (deprecated) file descriptors,
as described in r11081.

Improve lisp_read() a bit (when sockets or other handles with the
FILE_FLAG_OVERLAPPED bit set. It would make too much sense for Windows
to provide a way to determine whether this bit is set ...). Briefly,
GetOverlappedResult?() can return with no error and no data transferred
if the file handle is signalled as a result of I/O activity involving
it in another thread.

We may ultimately need to use a (thread-specific) event handle in
the "overlapped" structure to avoid these spurious wakeups. For the
time being, loop until we transfer some data or get an error.

(lisp_write() probably has the same problem, but we're not as likely
to block while doing a write.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/source/lisp-kernel/windows-calls.c

    r10966 r11085  
    176176#endif
    177177
    178 
     178#define MAX_FD 32
    179179
    180180int
    181181lisp_open(wchar_t *path, int flag, int mode)
    182182{
    183   int fd;
    184183  HANDLE hfile;
    185184  DWORD dwDesiredAccess = 0;
     
    263262  if (hfile == ((HANDLE)-1)) {
    264263    _dosmaperr(GetLastError());
    265     return -errno;
    266   }
    267   fd = _open_osfhandle((intptr_t)hfile, flag);
    268 
    269   if (fd < 0) {
    270     CloseHandle(hfile);
    271   }
    272   return fd;
     264    return -1;
     265  }
     266  return (int)hfile;
    273267}
    274268
     
    276270lisp_close(int fd)
    277271{
    278   return close(fd);
     272  if (fd < MAX_FD) {
     273    return close(fd);
     274  }
     275  if (CloseHandle((HANDLE)fd)) {
     276    return 0;
     277  }
     278  _dosmaperr(GetLastError());
     279  return -1;
    279280}
    280281
     
    289290  extern TCR *get_tcr(int);
    290291
    291   hfile = (HANDLE) _get_osfhandle(fd);
    292 
    293   if (hfile == ((HANDLE)-1)) {
    294     errno = EBADF;
    295     return -1;
     292  if (fd < MAX_FD) {
     293    hfile = (HANDLE) _get_osfhandle(fd);
     294    if (hfile == ((HANDLE)-1)) {
     295      errno = EBADF;
     296      return -1;
     297    }
     298  } else {
     299    hfile = (HANDLE) fd;
    296300  }
    297301 
     
    307311  tcr->foreign_exception_status = (signed_natural)&pending;
    308312
    309   if (ReadFile(hfile, buf, count, &nread, &overlapped)) {
    310     tcr->foreign_exception_status = 0;
    311     return nread;
    312   }
    313   err = GetLastError();
    314 
    315   if (err == ERROR_HANDLE_EOF) {
    316     tcr->foreign_exception_status = 0;
    317     return 0;
    318   }
    319 
    320   if (err != ERROR_IO_PENDING) {
    321     _dosmaperr(err);
    322     tcr->foreign_exception_status = 0;
    323     return -1;
    324   }
     313  do {
     314    if (ReadFile(hfile, buf, count, &nread, &overlapped)) {
     315      tcr->foreign_exception_status = 0;
     316      return nread;
     317    }
     318    err = GetLastError();
     319
     320    if (err == ERROR_HANDLE_EOF) {
     321      tcr->foreign_exception_status = 0;
     322      return 0;
     323    }
     324
     325    if (err != ERROR_IO_PENDING) {
     326      _dosmaperr(err);
     327      tcr->foreign_exception_status = 0;
     328      return -1;
     329    }
    325330 
    326   /* We block here */
    327   if (GetOverlappedResult(hfile, &overlapped, &nread, TRUE)) {
    328     tcr->foreign_exception_status = 0;
    329     return nread;
    330   }
    331   err = GetLastError();
     331    err = 0;
     332    /* We block here */
     333    if (GetOverlappedResult(hfile, &overlapped, &nread, TRUE)) {
     334      if (nread) {
     335        tcr->foreign_exception_status = 0;
     336        return nread;
     337      }
     338    } else {
     339      err = GetLastError();
     340    }
     341  } while (!err);
    332342  tcr->foreign_exception_status = 0;
    333343
     
    351361  DWORD err, nwritten;
    352362
    353   hfile = (HANDLE) _get_osfhandle(fd);
    354 
    355   if (hfile == ((HANDLE)-1)) {
    356     errno = EBADF;
    357     return -1;
     363  if (fd < MAX_FD) {
     364    hfile = (HANDLE) _get_osfhandle(fd);
     365
     366    if (hfile == ((HANDLE)-1)) {
     367      errno = EBADF;
     368      return -1;
     369    }
     370  } else {
     371    hfile = (HANDLE) fd;
    358372  }
    359373
     
    380394}
    381395
    382 off_t
     396__int64
    383397lisp_lseek(int fd, __int64 offset, int whence)
    384398{
    385   return lseek64(fd, offset, whence);
    386 }
    387 
     399  HANDLE hfile;
     400  DWORD high, low;
     401
     402  if (fd < MAX_FD) {
     403    hfile = (HANDLE) _get_osfhandle(fd);
     404
     405    if (hfile == ((HANDLE)-1)) {
     406      errno = EBADF;
     407      return -1;
     408    }
     409  } else {
     410    hfile = (HANDLE) fd;
     411  }
     412  high = ((__int64)offset)>>32;
     413  low = offset & 0xffffffff;
     414  low = SetFilePointer(hfile, low, &high, whence);
     415  if (low != INVALID_SET_FILE_POINTER) {
     416    return ((((__int64)high)<<32)|low);
     417  }
     418  _dosmaperr(GetLastError());
     419  return -1;
     420}
     421
     422#define ALL_USERS(f) ((f) | ((f)>> 3) | ((f >> 6)))
     423#define STAT_READONLY ALL_USERS(_S_IREAD)
     424#define STAT_READWRITE ALL_USERS((_S_IREAD|_S_IWRITE))
    388425int
    389426lisp_stat(wchar_t *path, struct __stat64 *buf)
     
    392429}
    393430
     431#define UNIX_EPOCH_IN_WINDOWS_EPOCH  116444736000000000LL
     432
     433__time64_t
     434filetime_to_unix_time(FILETIME *ft)
     435{
     436  __time64_t then = *((__time64_t *) ft);
     437
     438  then -= UNIX_EPOCH_IN_WINDOWS_EPOCH;
     439  return then/10000000;
     440}
     441
    394442int
    395443lisp_fstat(int fd, struct __stat64 *buf)
    396444{
    397   return _fstat64(fd,buf);
     445  HANDLE hfile;
     446  int filetype;
     447
     448  if (fd < MAX_FD) {
     449    hfile = (HANDLE) _get_osfhandle(fd);
     450
     451    if (hfile == ((HANDLE)-1)) {
     452      errno = EBADF;
     453      return -1;
     454    }
     455  } else {
     456    hfile = (HANDLE) fd;
     457  }
     458  filetype = GetFileType(hfile) & ~FILE_TYPE_REMOTE;
     459
     460  if (filetype == FILE_TYPE_UNKNOWN) {
     461    errno = EBADF;
     462    return -1;
     463  }
     464
     465  memset(buf, 0, sizeof(*buf));
     466  buf->st_nlink = 1;
     467 
     468  switch(filetype) {
     469  case FILE_TYPE_CHAR:
     470  case FILE_TYPE_PIPE:
     471    if (filetype == FILE_TYPE_CHAR) {
     472      buf->st_mode = _S_IFCHR;
     473    } else {
     474      buf->st_mode = _S_IFIFO;
     475    }
     476    break;
     477  case FILE_TYPE_DISK:
     478    {
     479      BY_HANDLE_FILE_INFORMATION info;
     480
     481      if (!GetFileInformationByHandle(hfile, &info)) {
     482        _dosmaperr(GetLastError());
     483        return -1;
     484      }
     485
     486      if (info.dwFileAttributes & FILE_ATTRIBUTE_READONLY) {
     487        buf->st_mode = STAT_READONLY;
     488      } else {
     489        buf->st_mode = STAT_READWRITE;
     490      }
     491      buf->st_mode |= _S_IFREG;
     492      buf->st_size = ((((__int64)(info.nFileSizeHigh))<<32LL) |
     493                      ((__int64)(info.nFileSizeLow)));
     494      buf->st_mtime = filetime_to_unix_time(&info.ftLastWriteTime);
     495      buf->st_atime = filetime_to_unix_time(&info.ftLastAccessTime);
     496      buf->st_ctime = filetime_to_unix_time(&info.ftCreationTime);
     497    }
     498    break;
     499  case FILE_TYPE_UNKNOWN:
     500  default:
     501    errno = EBADF;
     502    return -1;
     503  }
     504  return 0;
    398505}
    399506
     
    407514
    408515__int64
    409 lisp_ftruncate(int fd, __int64 new_size)
    410 {
    411   /* Note that _ftruncate only allows 32-bit length */
    412   return ftruncate(fd,(off_t)new_size);
    413 }
     516lisp_ftruncate(int fd, off_t new_size)
     517{
     518  HANDLE hfile;
     519  __int64 oldpos;
     520
     521  if (fd < MAX_FD) {
     522    hfile = (HANDLE) _get_osfhandle(fd);
     523
     524    if (hfile == ((HANDLE)-1)) {
     525      errno = EBADF;
     526      return -1;
     527    }
     528  } else {
     529    hfile = (HANDLE) fd;
     530  }
     531
     532  oldpos = lisp_lseek((int)hfile, 0, SEEK_END);
     533  if (oldpos == -1) {
     534    return 0;
     535  }
     536  if (oldpos < new_size) {
     537    char buf[4096];
     538    __int64 n = new_size-oldpos;
     539    DWORD nwritten, to_write;
     540
     541    memset(buf,0,sizeof(buf));
     542    while(n) {
     543      if (n > 4096LL) {
     544        to_write = 4096;
     545      } else {
     546        to_write = n;
     547      }
     548      if (!WriteFile(hfile,buf,to_write,&nwritten,NULL)) {
     549        _dosmaperr(GetLastError());
     550        return -1;
     551      }
     552      n -= nwritten;
     553    }
     554    return 0;
     555  }
     556  lisp_lseek((int)hfile, new_size, SEEK_SET);
     557  if (SetEndOfFile(hfile)) {
     558    return 0;
     559  }
     560  _dosmaperr(GetLastError());
     561  return -1;
     562}
     563
    414564
    415565_WDIR *
     
    446596      return -1;
    447597    }
    448   fd[0] = _open_osfhandle((intptr_t)input, 0);
    449   fd[1] = _open_osfhandle((intptr_t)output, 0);
     598  fd[0] = (int) input;
     599  fd[1] = (int) output;
    450600  return 0;
    451601}
Note: See TracChangeset for help on using the changeset viewer.