--- IO-AIO/AIO.xs 2007/05/09 06:45:12 1.98 +++ IO-AIO/AIO.xs 2007/06/01 05:51:21 1.99 @@ -20,6 +20,7 @@ #include #include #include +#include #if HAVE_SENDFILE # if __linux @@ -63,6 +64,9 @@ REQ_READ, REQ_WRITE, REQ_READAHEAD, REQ_SENDFILE, REQ_STAT, REQ_LSTAT, REQ_FSTAT, + REQ_UTIME, REQ_FUTIME, /* must be consecutive */ + REQ_CHMOD, REQ_FCHMOD, /* must be consecutive */ + REQ_CHOWN, REQ_FCHOWN, /* must be consecutive */ REQ_FSYNC, REQ_FDATASYNC, REQ_UNLINK, REQ_RMDIR, REQ_MKDIR, REQ_RENAME, REQ_MKNOD, REQ_READDIR, @@ -78,16 +82,17 @@ { struct aio_cb *volatile next; - SV *callback, *fh; + SV *callback; SV *sv1, *sv2; void *ptr1, *ptr2; off_t offs; size_t size; ssize_t result; + double nv1, nv2; STRLEN stroffset; int type; - int int1, int2; + int int1, int2, int3; int errorno; mode_t mode; /* open */ @@ -480,9 +485,9 @@ case REQ_READLINK: if (req->result > 0) { - SvCUR_set (req->sv1, req->result); - *SvEND (req->sv1) = 0; - PUSHs (req->sv1); + SvCUR_set (req->sv2, req->result); + *SvEND (req->sv2) = 0; + PUSHs (req->sv2); } break; @@ -496,8 +501,8 @@ break; case REQ_READ: - SvCUR_set (req->sv1, req->stroffset + (req->result > 0 ? req->result : 0)); - *SvEND (req->sv1) = 0; + SvCUR_set (req->sv2, req->stroffset + (req->result > 0 ? req->result : 0)); + *SvEND (req->sv2) = 0; PUSHs (sv_2mortal (newSViv (req->result))); break; @@ -541,7 +546,6 @@ SvREFCNT_dec (req->self); } - SvREFCNT_dec (req->fh); SvREFCNT_dec (req->sv1); SvREFCNT_dec (req->sv2); SvREFCNT_dec (req->callback); @@ -834,6 +838,34 @@ } #endif +#ifndef HAVE_FUTIMES + +# define utimes(path,times) aio_utimes (path, times) +# define futimes(fd,times) aio_futimes (fd, times) + +int aio_utimes (const char *filename, const struct timeval times[2]) +{ + if (times) + { + struct utimbuf buf; + + buf.actime = times[0].tv_sec; + buf.modtime = times[1].tv_sec; + + return utime (filename, &buf); + } + else + return utime (filename, 0); +} + +int aio_futimes (int fd, const struct timeval tv[2]) +{ + errno = ENOSYS; + return -1; +} + +#endif + #if !HAVE_FDATASYNC # define fdatasync fsync #endif @@ -1111,6 +1143,11 @@ case REQ_LSTAT: req->result = lstat (req->ptr1, (Stat_t *)req->ptr2); break; case REQ_FSTAT: req->result = fstat (req->int1, (Stat_t *)req->ptr2); break; + case REQ_CHOWN: req->result = chown (req->ptr1, req->int2, req->int3); break; + case REQ_FCHOWN: req->result = fchown (req->int1, req->int2, req->int3); break; + case REQ_CHMOD: req->result = chmod (req->ptr1, req->mode); break; + case REQ_FCHMOD: req->result = fchmod (req->int1, req->mode); break; + case REQ_OPEN: req->result = open (req->ptr1, req->int1, req->mode); break; case REQ_CLOSE: req->result = close (req->int1); break; case REQ_UNLINK: req->result = unlink (req->ptr1); break; @@ -1130,12 +1167,36 @@ { struct timeval tv; - tv.tv_sec = req->int1; - tv.tv_usec = req->int2; + tv.tv_sec = req->nv1; + tv.tv_usec = (req->nv1 - tv.tv_usec) * 1000000.; req->result = select (0, 0, 0, 0, &tv); } + case REQ_UTIME: + case REQ_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) * 1000000.; + tv[1].tv_sec = req->nv2; + tv[1].tv_usec = (req->nv2 - tv[1].tv_sec) * 1000000.; + + times = tv; + } + else + times = 0; + + + req->result = req->type == REQ_FUTIME + ? futimes (req->int1, times) + : utimes (req->ptr1, times); + } + case REQ_GROUP: case REQ_NOP: break; @@ -1144,7 +1205,7 @@ goto quit; default: - req->result = ENOSYS; + req->result = -1; break; } @@ -1317,11 +1378,7 @@ RETVAL void -aio_open (pathname,flags,mode,callback=&PL_sv_undef) - SV8 * pathname - int flags - int mode - SV * callback +aio_open (SV8 *pathname, int flags, int mode, SV *callback=&PL_sv_undef) PROTOTYPE: $$$;$ PPCODE: { @@ -1337,9 +1394,7 @@ } void -aio_close (fh,callback=&PL_sv_undef) - SV * fh - SV * callback +aio_close (SV *fh, SV *callback=&PL_sv_undef) PROTOTYPE: $;$ ALIAS: aio_close = REQ_CLOSE @@ -1350,20 +1405,14 @@ dREQ; req->type = ix; - req->fh = newSVsv (fh); + req->sv1 = newSVsv (fh); req->int1 = PerlIO_fileno (IoIFP (sv_2io (fh))); REQ_SEND (req); } void -aio_read (fh,offset,length,data,dataoffset,callback=&PL_sv_undef) - SV * fh - UV offset - UV length - SV8 * data - UV dataoffset - SV * callback +aio_read (SV *fh, UV offset, UV length, SV8 *data, UV dataoffset, SV *callback=&PL_sv_undef) ALIAS: aio_read = REQ_READ aio_write = REQ_WRITE @@ -1401,12 +1450,12 @@ dREQ; req->type = ix; - req->fh = newSVsv (fh); + req->sv1 = newSVsv (fh); req->int1 = PerlIO_fileno (ix == REQ_READ ? IoIFP (sv_2io (fh)) : IoOFP (sv_2io (fh))); req->offs = offset; req->size = length; - req->sv1 = SvREFCNT_inc (data); + req->sv2 = SvREFCNT_inc (data); req->ptr1 = (char *)svptr + dataoffset; req->stroffset = dataoffset; @@ -1421,9 +1470,7 @@ } void -aio_readlink (path,callback=&PL_sv_undef) - SV8 * path - SV * callback +aio_readlink (SV8 *path, SV *callback=&PL_sv_undef) PROTOTYPE: $$;$ PPCODE: { @@ -1434,28 +1481,23 @@ SvPOK_on (data); req->type = REQ_READLINK; - req->fh = newSVsv (path); - req->ptr2 = SvPVbyte_nolen (req->fh); - req->sv1 = data; + req->sv1 = newSVsv (path); + req->ptr2 = SvPVbyte_nolen (req->sv1); + req->sv2 = data; req->ptr1 = SvPVbyte_nolen (data); REQ_SEND; } void -aio_sendfile (out_fh,in_fh,in_offset,length,callback=&PL_sv_undef) - SV * out_fh - SV * in_fh - UV in_offset - UV length - SV * callback +aio_sendfile (SV *out_fh, SV *in_fh, UV in_offset, UV length, SV *callback=&PL_sv_undef) PROTOTYPE: $$$$;$ PPCODE: { dREQ; req->type = REQ_SENDFILE; - req->fh = newSVsv (out_fh); + req->sv1 = newSVsv (out_fh); req->int1 = PerlIO_fileno (IoIFP (sv_2io (out_fh))); req->sv2 = newSVsv (in_fh); req->int2 = PerlIO_fileno (IoIFP (sv_2io (in_fh))); @@ -1466,18 +1508,14 @@ } void -aio_readahead (fh,offset,length,callback=&PL_sv_undef) - SV * fh - UV offset - IV length - SV * callback +aio_readahead (SV *fh, UV offset, IV length, SV *callback=&PL_sv_undef) PROTOTYPE: $$$;$ PPCODE: { dREQ; req->type = REQ_READAHEAD; - req->fh = newSVsv (fh); + req->sv1 = newSVsv (fh); req->int1 = PerlIO_fileno (IoIFP (sv_2io (fh))); req->offs = offset; req->size = length; @@ -1486,9 +1524,7 @@ } void -aio_stat (fh_or_path,callback=&PL_sv_undef) - SV8 * fh_or_path - SV * callback +aio_stat (SV8 *fh_or_path, SV *callback=&PL_sv_undef) ALIAS: aio_stat = REQ_STAT aio_lstat = REQ_LSTAT @@ -1504,17 +1540,16 @@ } req->flags |= FLAG_PTR2_FREE; + req->sv1 = newSVsv (fh_or_path); if (SvPOK (fh_or_path)) { req->type = ix; - req->sv1 = newSVsv (fh_or_path); req->ptr1 = SvPVbyte_nolen (req->sv1); } else { req->type = REQ_FSTAT; - req->fh = newSVsv (fh_or_path); req->int1 = PerlIO_fileno (IoIFP (sv_2io (fh_or_path))); } @@ -1522,9 +1557,78 @@ } void -aio_unlink (pathname,callback=&PL_sv_undef) - SV8 * pathname - SV * callback +aio_utime (SV8 *fh_or_path, SV *atime, SV *mtime, SV *callback=&PL_sv_undef) + PPCODE: +{ + dREQ; + + req->nv1 = SvOK (atime) ? SvNV (atime) : -1.; + req->nv2 = SvOK (mtime) ? SvNV (mtime) : -1.; + req->sv1 = newSVsv (fh_or_path); + + if (SvPOK (fh_or_path)) + { + req->type = REQ_UTIME; + req->ptr1 = SvPVbyte_nolen (req->sv1); + } + else + { + req->type = REQ_FUTIME; + req->int1 = PerlIO_fileno (IoIFP (sv_2io (fh_or_path))); + } + + REQ_SEND; +} + +void +aio_chmod (SV8 *fh_or_path, int mode, SV *callback=&PL_sv_undef) + PPCODE: +{ + dREQ; + + req->mode = mode; + req->sv1 = newSVsv (fh_or_path); + + if (SvPOK (fh_or_path)) + { + req->type = REQ_CHMOD; + req->ptr1 = SvPVbyte_nolen (req->sv1); + } + else + { + req->type = REQ_FCHMOD; + req->int1 = PerlIO_fileno (IoIFP (sv_2io (fh_or_path))); + } + + REQ_SEND; +} + +void +aio_chown (SV8 *fh_or_path, SV *uid, SV *gid, SV *callback=&PL_sv_undef) + PPCODE: +{ + dREQ; + + req->int2 = SvOK (uid) ? SvIV (uid) : -1; + req->int3 = SvOK (gid) ? SvIV (gid) : -1; + req->sv1 = newSVsv (fh_or_path); + + if (SvPOK (fh_or_path)) + { + req->type = REQ_CHOWN; + req->ptr1 = SvPVbyte_nolen (req->sv1); + } + else + { + req->type = REQ_FCHOWN; + req->int1 = PerlIO_fileno (IoIFP (sv_2io (fh_or_path))); + } + + REQ_SEND; +} + +void +aio_unlink (SV8 *pathname, SV *callback=&PL_sv_undef) ALIAS: aio_unlink = REQ_UNLINK aio_rmdir = REQ_RMDIR @@ -1541,10 +1645,7 @@ } void -aio_mkdir (pathname,mode,callback=&PL_sv_undef) - SV8 * pathname - UV mode - SV * callback +aio_mkdir (SV8 *pathname, int mode, SV *callback=&PL_sv_undef) PPCODE: { dREQ; @@ -1558,10 +1659,7 @@ } void -aio_link (oldpath,newpath,callback=&PL_sv_undef) - SV8 * oldpath - SV8 * newpath - SV * callback +aio_link (SV8 *oldpath, SV8 *newpath, SV *callback=&PL_sv_undef) ALIAS: aio_link = REQ_LINK aio_symlink = REQ_SYMLINK @@ -1571,8 +1669,8 @@ dREQ; req->type = ix; - req->fh = newSVsv (oldpath); - req->ptr2 = SvPVbyte_nolen (req->fh); + req->sv2 = newSVsv (oldpath); + req->ptr2 = SvPVbyte_nolen (req->sv2); req->sv1 = newSVsv (newpath); req->ptr1 = SvPVbyte_nolen (req->sv1); @@ -1580,11 +1678,7 @@ } void -aio_mknod (pathname,mode,dev,callback=&PL_sv_undef) - SV8 * pathname - UV mode - UV dev - SV * callback +aio_mknod (SV8 *pathname, int mode, UV dev, SV *callback=&PL_sv_undef) PPCODE: { dREQ; @@ -1599,23 +1693,19 @@ } void -aio_busy (delay,callback=&PL_sv_undef) - double delay - SV * callback +aio_busy (double delay, SV *callback=&PL_sv_undef) PPCODE: { dREQ; req->type = REQ_BUSY; - req->int1 = delay < 0. ? 0 : delay; - req->int2 = delay < 0. ? 0 : 1000. * (delay - req->int1); + req->nv1 = delay < 0. ? 0. : delay; REQ_SEND; } void -aio_group (callback=&PL_sv_undef) - SV * callback +aio_group (SV *callback=&PL_sv_undef) PROTOTYPE: ;$ PPCODE: { @@ -1628,8 +1718,7 @@ } void -aio_nop (callback=&PL_sv_undef) - SV * callback +aio_nop (SV *callback=&PL_sv_undef) PPCODE: { dREQ;