IO-AIO

 view release on metacpan or  search on metacpan

libeio/eio.c  view on Meta::CPAN

# define ECANCELED EDOM
#endif
#ifndef ELOOP
# define ELOOP EDOM
#endif

#if !defined(ENOTSOCK) && defined(WSAENOTSOCK)
# define ENOTSOCK WSAENOTSOCK
#endif

static void eio_destroy (eio_req *req);

#ifndef EIO_FINISH
# define EIO_FINISH(req)  ((req)->finish) && !EIO_CANCELLED (req) ? (req)->finish (req) : 0
#endif

#ifndef EIO_DESTROY
# define EIO_DESTROY(req) do { if ((req)->destroy) (req)->destroy (req); } while (0)
#endif

#ifndef EIO_FEED
# define EIO_FEED(req)    do { if ((req)->feed   ) (req)->feed    (req); } while (0)
#endif

#ifndef EIO_FD_TO_WIN32_HANDLE
# define EIO_FD_TO_WIN32_HANDLE(fd) _get_osfhandle (fd)
#endif
#ifndef EIO_WIN32_HANDLE_TO_FD
# define EIO_WIN32_HANDLE_TO_FD(handle) _open_osfhandle (handle, 0)
#endif

#define EIO_ERRNO(errval,retval) ((errno = errval), retval)

#define EIO_ENOSYS() EIO_ERRNO (ENOSYS, -1)

#ifdef _WIN32

  #undef PAGESIZE
  #define PAGESIZE 4096 /* GetSystemInfo? */

  /* TODO: look at how perl does stat (non-sloppy), unlink (ro-files), utime, link */

  #ifdef EIO_STRUCT_STATI64
    /* look at perl's non-sloppy stat */
    #define stat(path,buf)       _stati64 (path,buf)
    #define fstat(fd,buf)        _fstati64 (fd,buf)
  #endif
  #define lstat(path,buf)      stat (path,buf)
  #define fsync(fd)            (FlushFileBuffers ((HANDLE)EIO_FD_TO_WIN32_HANDLE (fd)) ? 0 : EIO_ERRNO (EBADF, -1))
  #define mkdir(path,mode)     _mkdir (path)
  #define link(old,neu)        (CreateHardLink (neu, old, 0) ? 0 : EIO_ERRNO (ENOENT, -1))

  #define chmod(path,mode)     _chmod (path, mode)
  #define dup(fd)              _dup (fd)
  #define dup2(fd1,fd2)        _dup2 (fd1, fd2)
  #define pipe(fds)            _pipe (fds, 4096, O_BINARY)

  #define fcntl(fd,cmd,arg)    EIO_ENOSYS ()
  #define ioctl(fd,cmd,arg)    EIO_ENOSYS ()
  #define fchmod(fd,mode)      EIO_ENOSYS ()
  #define chown(path,uid,gid)  EIO_ENOSYS ()
  #define fchown(fd,uid,gid)   EIO_ENOSYS ()
  #define truncate(path,offs)  EIO_ENOSYS () /* far-miss: SetEndOfFile */
  #define ftruncate(fd,offs)   EIO_ENOSYS () /* near-miss: SetEndOfFile */
  #define mknod(path,mode,dev) EIO_ENOSYS ()
  #define sync()               EIO_ENOSYS ()
  #define readlink(path,buf,s) EIO_ENOSYS ()
  #define statvfs(path,buf)    EIO_ENOSYS ()
  #define fstatvfs(fd,buf)     EIO_ENOSYS ()

  #define pread(fd,buf,count,offset)  eio__pread  (fd, buf, count, offset)
  #define pwrite(fd,buf,count,offset) eio__pwrite (fd, buf, count, offset)

  #if __GNUC__
    typedef long long eio_off_t; /* signed for compatibility to msvc */
  #else
    typedef __int64   eio_off_t; /* unsigned not supported by msvc */
  #endif

  static eio_ssize_t
  eio__pread (int fd, void *buf, eio_ssize_t count, eio_off_t offset)
  {
    OVERLAPPED o = { 0 };
    DWORD got;

    o.Offset     = offset;
    o.OffsetHigh = offset >> 32;

    return ReadFile ((HANDLE)EIO_FD_TO_WIN32_HANDLE (fd), buf, count, &got, &o)
         ? got : -1;
  }

  static eio_ssize_t
  eio__pwrite (int fd, void *buf, eio_ssize_t count, eio_off_t offset)
  {
    OVERLAPPED o = { 0 };
    DWORD got;

    o.Offset     = offset;
    o.OffsetHigh = offset >> 32;

    return WriteFile ((HANDLE)EIO_FD_TO_WIN32_HANDLE (fd), buf, count, &got, &o)
         ? got : -1;
  }

  /* rename() uses MoveFile, which fails to overwrite */
  #define rename(old,neu)      eio__rename (old, neu)

  static int
  eio__rename (const char *old, const char *neu)
  {
    if (MoveFileEx (old, neu, MOVEFILE_REPLACE_EXISTING))
      return 0;

    /* should steal _dosmaperr */
    switch (GetLastError ())
      {
        case ERROR_FILE_NOT_FOUND:
        case ERROR_PATH_NOT_FOUND:
        case ERROR_INVALID_DRIVE:
        case ERROR_NO_MORE_FILES:
        case ERROR_BAD_NETPATH:

libeio/eio.c  view on Meta::CPAN

eio_execute (etp_worker *self, eio_req *req)
{
#if HAVE_AT
  int dirfd;
#else
  const char *path;
#endif

  if (ecb_expect_false (EIO_CANCELLED (req)))
    {
      req->result  = -1;
      req->errorno = ECANCELED;
      return;
    }

  if (ecb_expect_false (req->wd == EIO_INVALID_WD))
    {
      req->result  = -1;
      req->errorno = ENOENT;
      return;
    }

  if (req->type >= EIO_OPEN)
    {
      #if HAVE_AT
        dirfd = WD2FD (req->wd);
      #else
        path = wd_expand (&self->tmpbuf, req->wd, req->ptr1);
      #endif
    }

  switch (req->type)
    {
      case EIO_WD_OPEN:   req->wd = eio__wd_open_sync (&self->tmpbuf, req->wd, req->ptr1);
                          req->result = req->wd == EIO_INVALID_WD ? -1 : 0;
                          break;
      case EIO_WD_CLOSE:  req->result = 0;
                          eio_wd_close_sync (req->wd); break;

      case EIO_SEEK:      eio__lseek (req); break;
      case EIO_READ:      ALLOC (req->size);
                          req->result = req->offs >= 0
                                      ? pread     (req->int1, req->ptr2, req->size, req->offs)
                                      : read      (req->int1, req->ptr2, req->size); break;
      case EIO_WRITE:     req->result = req->offs >= 0
                                      ? pwrite    (req->int1, req->ptr2, req->size, req->offs)
                                      : write     (req->int1, req->ptr2, req->size); break;

      case EIO_FCNTL:     req->result = fcntl     (req->int1, (int)          req->int2, req->ptr2); break;
      case EIO_IOCTL:     req->result = ioctl     (req->int1, (unsigned long)req->int2, req->ptr2); break;

      case EIO_READAHEAD: req->result = readahead     (req->int1, req->offs, req->size); break;
      case EIO_SENDFILE:  req->result = eio__sendfile (req->int1, req->int2, req->offs, req->size); break;

#if HAVE_AT

      case EIO_STAT:      ALLOC (sizeof (EIO_STRUCT_STAT));
                          req->result = fstatat   (dirfd, req->ptr1, (EIO_STRUCT_STAT *)req->ptr2, 0); break;
      case EIO_LSTAT:     ALLOC (sizeof (EIO_STRUCT_STAT));
                          req->result = fstatat   (dirfd, req->ptr1, (EIO_STRUCT_STAT *)req->ptr2, AT_SYMLINK_NOFOLLOW); break;
      case EIO_CHOWN:     req->result = fchownat  (dirfd, req->ptr1, req->int2, req->int3, 0); break;
      case EIO_CHMOD:     req->result = fchmodat  (dirfd, req->ptr1, (mode_t)req->int2, 0); break;
      case EIO_TRUNCATE:  req->result = eio__truncateat (dirfd, req->ptr1, req->offs); break;
      case EIO_OPEN:      req->result = openat    (dirfd, req->ptr1, req->int1, (mode_t)req->int2); break;
      case EIO_SLURP:     eio__slurp (  openat    (dirfd, req->ptr1, O_RDONLY | O_CLOEXEC), req); break;

      case EIO_UNLINK:    req->result = unlinkat  (dirfd, req->ptr1, 0); break;
      case EIO_RMDIR:     /* complications arise because "." cannot be removed, so we might have to expand */
                          req->result = req->wd && SINGLEDOT (req->ptr1)
                             ? rmdir (req->wd->str)
                             : unlinkat (dirfd, req->ptr1, AT_REMOVEDIR); break;
      case EIO_MKDIR:     req->result = mkdirat   (dirfd, req->ptr1, (mode_t)req->int2); break;
      case EIO_RENAME:    req->result = eio__renameat2 (
                            dirfd,
                            /* complications arise because "." cannot be renamed, so we might have to expand */
                            req->wd && SINGLEDOT (req->ptr1) ? req->wd->str : req->ptr1,
                            WD2FD ((eio_wd)req->int3),
                            req->ptr2,
                            req->int2
                          );
                          break;
      case EIO_LINK:      req->result = linkat    (dirfd, req->ptr1, WD2FD ((eio_wd)req->int3), req->ptr2, 0); break;
      case EIO_SYMLINK:   req->result = symlinkat (req->ptr1, dirfd, req->ptr2); break;
      case EIO_MKNOD:     req->result = mknodat   (dirfd, req->ptr1, (mode_t)req->int2, (dev_t)req->offs); break;
      case EIO_STATVFS:   ALLOC (sizeof (EIO_STRUCT_STATVFS));
                          req->result = eio__statvfsat (dirfd, req->ptr1, (EIO_STRUCT_STATVFS *)req->ptr2); break;
      case EIO_READLINK:  ALLOC (EIO_PATH_MAX);
                          req->result = readlinkat (dirfd, req->ptr1, req->ptr2, EIO_PATH_MAX);
                          if (req->result == EIO_PATH_MAX)
                            {
                              req->result = -1;
                              errno = ENAMETOOLONG;
                            }
                          break;
      case EIO_UTIME:
      case EIO_FUTIME:
        {
          struct timespec ts[2];
          struct timespec *times;

          if (req->nv1 != -1. || req->nv2 != -1.)
            {
              ts[0].tv_sec  = req->nv1;
              ts[0].tv_nsec = (req->nv1 - ts[0].tv_sec) * 1e9;
              ts[1].tv_sec  = req->nv2;
              ts[1].tv_nsec = (req->nv2 - ts[1].tv_sec) * 1e9;

              times = ts;
            }
          else
            times = 0;

          req->result = req->type == EIO_FUTIME
                        ? futimens  (req->int1, times)
                        : utimensat (dirfd, req->ptr1, times, 0);
        }
        break;

#else

      case EIO_STAT:      ALLOC (sizeof (EIO_STRUCT_STAT));
                          req->result = stat      (path     , (EIO_STRUCT_STAT *)req->ptr2); break;
      case EIO_LSTAT:     ALLOC (sizeof (EIO_STRUCT_STAT));
                          req->result = lstat     (path     , (EIO_STRUCT_STAT *)req->ptr2); break;
      case EIO_CHOWN:     req->result = chown     (path     , req->int2, req->int3); break;
      case EIO_CHMOD:     req->result = chmod     (path     , (mode_t)req->int2); break;
      case EIO_TRUNCATE:  req->result = truncate  (path     , req->offs); break;
      case EIO_OPEN:      req->result = open      (path     , req->int1, (mode_t)req->int2); break;
      case EIO_SLURP:     eio__slurp (  open      (path     , O_RDONLY | O_CLOEXEC), req); break;

      case EIO_UNLINK:    req->result = unlink    (path     ); break;
      case EIO_RMDIR:     req->result = rmdir     (path     ); break;
      case EIO_MKDIR:     req->result = mkdir     (path     , (mode_t)req->int2); break;
      case EIO_RENAME:    req->result = req->int2 ? EIO_ENOSYS () : rename (path, req->ptr2); break;
      case EIO_LINK:      req->result = link      (path     , req->ptr2); break;
      case EIO_SYMLINK:   req->result = symlink   (path     , req->ptr2); break;
      case EIO_MKNOD:     req->result = mknod     (path     , (mode_t)req->int2, (dev_t)req->offs); break;
      case EIO_STATVFS:   ALLOC (sizeof (EIO_STRUCT_STATVFS));
                          req->result = statvfs   (path     , (EIO_STRUCT_STATVFS *)req->ptr2); break;
      case EIO_READLINK:  ALLOC (EIO_PATH_MAX);
                          req->result = readlink (path, req->ptr2, EIO_PATH_MAX);
                          if (req->result == EIO_PATH_MAX)
                            {
                              req->result = -1;
                              errno = ENAMETOOLONG;
                            }
                          break;

      case EIO_UTIME:
      case EIO_FUTIME:
        {
          struct timeval tv[2];
          struct timeval *times;

          if (req->nv1 != -1. || req->nv2 != -1.)
            {
              tv[0].tv_sec  = req->nv1;
              tv[0].tv_usec = (req->nv1 - tv[0].tv_sec) * 1e6;
              tv[1].tv_sec  = req->nv2;
              tv[1].tv_usec = (req->nv2 - tv[1].tv_sec) * 1e6;

              times = tv;
            }
          else
            times = 0;

          req->result = req->type == EIO_FUTIME
                        ? futimes (req->int1, times)
                        : utimes  (req->ptr1, times);
        }
        break;

#endif

      case EIO_REALPATH:  if (0 <= (req->result = eio__realpath (&self->tmpbuf, req->wd, req->ptr1)))
                            {
                              ALLOC (req->result);
                              memcpy (req->ptr2, self->tmpbuf.ptr, req->result);
                            }
                           break;

      case EIO_FSTAT:     ALLOC (sizeof (EIO_STRUCT_STAT));
                          req->result = fstat     (req->int1, (EIO_STRUCT_STAT *)req->ptr2); break;

      case EIO_FSTATVFS:  ALLOC (sizeof (EIO_STRUCT_STATVFS));
                          req->result = fstatvfs  (req->int1, (EIO_STRUCT_STATVFS *)req->ptr2); break;

      case EIO_FCHOWN:    req->result = fchown    (req->int1, req->int2, req->int3); break;
      case EIO_FCHMOD:    req->result = fchmod    (req->int1, (mode_t)req->int2); break;
      case EIO_FTRUNCATE: req->result = ftruncate (req->int1, req->offs); break;

      case EIO_CLOSE:     req->result = eio__close (req->int1); break;
      case EIO_DUP2:      req->result = dup2      (req->int1, req->int2); break;
      case EIO_SYNC:      req->result = 0; sync (); break;
      case EIO_FSYNC:     req->result = fsync     (req->int1); break;
      case EIO_FDATASYNC: req->result = fdatasync (req->int1); break;
      case EIO_SYNCFS:    req->result = eio__syncfs (req->int1); break;
      case EIO_SYNC_FILE_RANGE: req->result = eio__sync_file_range (req->int1, req->offs, req->size, req->int2); break;
      case EIO_MSYNC:     req->result = eio__msync (req->ptr2, req->size, req->int1); break;
      case EIO_MTOUCH:    req->result = eio__mtouch (req); break;
      case EIO_MLOCK:     req->result = eio__mlock (req->ptr2, req->size); break;
      case EIO_MLOCKALL:  req->result = eio__mlockall (req->int1); break;
      case EIO_FALLOCATE: req->result = eio__fallocate (req->int1, req->int2, req->offs, req->size); break;

      case EIO_READDIR:   eio__scandir (req, self); break;

      case EIO_BUSY:
#ifdef _WIN32
	Sleep (req->nv1 * 1e3);
#else
        {
          struct timeval tv;

          tv.tv_sec  = req->nv1;
          tv.tv_usec = (req->nv1 - tv.tv_sec) * 1e6;

          req->result = select (0, 0, 0, 0, &tv);
        }
#endif
        break;

#if 0
      case EIO_GROUP:
        abort (); /* handled in eio_request */
#endif

      case EIO_NOP:
        req->result = 0;
        break;

      case EIO_CUSTOM:
        req->feed (req);
        break;

      default:
        req->result = EIO_ENOSYS ();
        break;
    }

alloc_fail:
  req->errorno = errno;
}

#ifndef EIO_NO_WRAPPERS

eio_req *eio_wd_open (const char *path, int pri, eio_cb cb, void *data)
{
  REQ (EIO_WD_OPEN); PATH; SEND;

libeio/eio.c  view on Meta::CPAN

eio_req *eio_close (int fd, int pri, eio_cb cb, void *data)
{
  REQ (EIO_CLOSE); req->int1 = fd; SEND;
}

eio_req *eio_readahead (int fd, off_t offset, size_t length, int pri, eio_cb cb, void *data)
{
  REQ (EIO_READAHEAD); req->int1 = fd; req->offs = offset; req->size = length; SEND;
}

eio_req *eio_seek (int fd, off_t offset, int whence, int pri, eio_cb cb, void *data)
{
  REQ (EIO_SEEK); req->int1 = fd; req->offs = offset; req->int2 = whence; SEND;
}

eio_req *eio_read (int fd, void *buf, size_t length, off_t offset, int pri, eio_cb cb, void *data)
{
  REQ (EIO_READ); req->int1 = fd; req->offs = offset; req->size = length; req->ptr2 = buf; SEND;
}

eio_req *eio_write (int fd, void *buf, size_t length, off_t offset, int pri, eio_cb cb, void *data)
{
  REQ (EIO_WRITE); req->int1 = fd; req->offs = offset; req->size = length; req->ptr2 = buf; SEND;
}

eio_req *eio_fcntl (int fd, int cmd, void *arg, int pri, eio_cb cb, void *data)
{
  REQ (EIO_IOCTL); req->int1 = fd; req->int2 = cmd; req->ptr2 = arg; SEND;
}

eio_req *eio_ioctl (int fd, unsigned long request, void *buf, int pri, eio_cb cb, void *data)
{
  REQ (EIO_IOCTL); req->int1 = fd; req->int2 = request; req->ptr2 = buf; SEND;
}

eio_req *eio_fstat (int fd, int pri, eio_cb cb, void *data)
{
  REQ (EIO_FSTAT); req->int1 = fd; SEND;
}

eio_req *eio_fstatvfs (int fd, int pri, eio_cb cb, void *data)
{
  REQ (EIO_FSTATVFS); req->int1 = fd; SEND;
}

eio_req *eio_futime (int fd, double atime, double mtime, int pri, eio_cb cb, void *data)
{
  REQ (EIO_FUTIME); req->int1 = fd; req->nv1 = atime; req->nv2 = mtime; SEND;
}

eio_req *eio_ftruncate (int fd, off_t offset, int pri, eio_cb cb, void *data)
{
  REQ (EIO_FTRUNCATE); req->int1 = fd; req->offs = offset; SEND;
}

eio_req *eio_fchmod (int fd, mode_t mode, int pri, eio_cb cb, void *data)
{
  REQ (EIO_FCHMOD); req->int1 = fd; req->int2 = (long)mode; SEND;
}

eio_req *eio_fchown (int fd, eio_uid_t uid, eio_gid_t gid, int pri, eio_cb cb, void *data)
{
  REQ (EIO_FCHOWN); req->int1 = fd; req->int2 = (long)uid; req->int3 = (long)gid; SEND;
}

eio_req *eio_dup2 (int fd, int fd2, int pri, eio_cb cb, void *data)
{
  REQ (EIO_DUP2); req->int1 = fd; req->int2 = fd2; SEND;
}

eio_req *eio_sendfile (int out_fd, int in_fd, off_t in_offset, size_t length, int pri, eio_cb cb, void *data)
{
  REQ (EIO_SENDFILE); req->int1 = out_fd; req->int2 = in_fd; req->offs = in_offset; req->size = length; SEND;
}

eio_req *eio_open (const char *path, int flags, mode_t mode, int pri, eio_cb cb, void *data)
{
  REQ (EIO_OPEN); PATH; req->int1 = flags; req->int2 = (long)mode; SEND;
}

eio_req *eio_utime (const char *path, double atime, double mtime, int pri, eio_cb cb, void *data)
{
  REQ (EIO_UTIME); PATH; req->nv1 = atime; req->nv2 = mtime; SEND;
}

eio_req *eio_truncate (const char *path, off_t offset, int pri, eio_cb cb, void *data)
{
  REQ (EIO_TRUNCATE); PATH; req->offs = offset; SEND;
}

eio_req *eio_chown (const char *path, eio_uid_t uid, eio_gid_t gid, int pri, eio_cb cb, void *data)
{
  REQ (EIO_CHOWN); PATH; req->int2 = (long)uid; req->int3 = (long)gid; SEND;
}

eio_req *eio_chmod (const char *path, mode_t mode, int pri, eio_cb cb, void *data)
{
  REQ (EIO_CHMOD); PATH; req->int2 = (long)mode; SEND;
}

eio_req *eio_mkdir (const char *path, mode_t mode, int pri, eio_cb cb, void *data)
{
  REQ (EIO_MKDIR); PATH; req->int2 = (long)mode; SEND;
}

static eio_req *
eio__1path (int type, const char *path, int pri, eio_cb cb, void *data)
{
  REQ (type); PATH; SEND;
}

eio_req *eio_readlink (const char *path, int pri, eio_cb cb, void *data)
{
  return eio__1path (EIO_READLINK, path, pri, cb, data);
}

eio_req *eio_realpath (const char *path, int pri, eio_cb cb, void *data)
{
  return eio__1path (EIO_REALPATH, path, pri, cb, data);
}

eio_req *eio_stat (const char *path, int pri, eio_cb cb, void *data)
{
  return eio__1path (EIO_STAT, path, pri, cb, data);
}

eio_req *eio_lstat (const char *path, int pri, eio_cb cb, void *data)
{
  return eio__1path (EIO_LSTAT, path, pri, cb, data);
}

eio_req *eio_statvfs (const char *path, int pri, eio_cb cb, void *data)
{
  return eio__1path (EIO_STATVFS, path, pri, cb, data);
}

eio_req *eio_unlink (const char *path, int pri, eio_cb cb, void *data)
{
  return eio__1path (EIO_UNLINK, path, pri, cb, data);
}

eio_req *eio_rmdir (const char *path, int pri, eio_cb cb, void *data)
{
  return eio__1path (EIO_RMDIR, path, pri, cb, data);
}

eio_req *eio_readdir (const char *path, int flags, int pri, eio_cb cb, void *data)
{
  REQ (EIO_READDIR); PATH; req->int1 = flags; SEND;
}



( run in 0.491 second using v1.01-cache-2.11-cpan-71847e10f99 )