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 )