#SYSSEEK
########
SV*
sysseek(fd,offset,whence)
SV *fd;
long offset;
int whence;
INIT:
long ret;
CODE:
if(SvOK(fd) && SvIOK(fd)){
ret=lseek(SvIV(fd), offset, whence);
if(ret<0){
RETVAL=&PL_sv_undef;
}
else{
RETVAL=newSViv(ret);
}
}
else{
errno=EBADF;
RETVAL=&PL_sv_undef;
Perl_warn(aTHX_ "%s", "IO::FD::bind called with something other than a file descriptor");
}
OUTPUT:
RETVAL
#DUP
####
SV*
dup(fd)
SV *fd;
INIT:
int ret;
CODE:
if(SvOK(fd) && SvIOK(fd)){
ret=dup(SvIV(fd));
if(ret<0){
RETVAL=&PL_sv_undef;
}
else{
RETVAL=newSViv(ret);
}
}
else {
errno=EBADF;
RETVAL=&PL_sv_undef;
Perl_warn(aTHX_ "%s", "IO::FD::dup called with something other than a file descriptor");
}
OUTPUT:
RETVAL
#DUP2
#####
SV*
dup2(fd1,fd2)
SV *fd1
SV *fd2
INIT:
int ret;
CODE:
if(SvOK(fd1) && SvIOK(fd1) && SvOK(fd2) && SvIOK(fd2)){
ret=dup2(SvIV(fd1),SvIV(fd2));
if(ret<0){
RETVAL=&PL_sv_undef;
}
else{
if(ret>PL_maxsysfd){
fcntl(ret, F_SETFD, FD_CLOEXEC);
}
RETVAL=newSViv(ret);
}
}
else {
errno=EBADF;
RETVAL=&PL_sv_undef;
Perl_warn(aTHX_ "%s", "IO::FD::dup2 called with something other than a file descriptor");
}
OUTPUT:
RETVAL
#FCNTL
######
SV*
fcntl(fd, cmd, arg)
SV *fd
int cmd
SV* arg
#TODO: everything
ALIAS: sysfctrl=1
INIT:
int ret;
CODE:
if(SvOK(fd) && SvIOK(fd)){
//if arg is numeric, call with iv
//otherwise we pass pointers and hope for the best
if(SvOK(arg)){
if(SvIOK(arg)){
//fprintf(stderr, "PROCESSING ARG AS NUMBER\n");
ret=fcntl(SvIV(fd),cmd, SvIV(arg));
}else if(SvPOK(arg)){
//fprintf(stderr, "PROCESSING ARG AS STRING\n");
ret=fcntl(SvIV(fd),cmd,SvPVX(arg));
}
else {
//error
//fprintf(stderr, "PROCESSING ARG AS UNKOWN\n");
ret=-1;
}
if(ret==-1){
RETVAL=&PL_sv_undef;
}
else {
RETVAL=newSViv(ret);
}
}
}
else {
errno=EBADF;
RETVAL=&PL_sv_undef;
Perl_warn(aTHX_ "%s", "IO::FD::fcntl called with something other than a file descriptor");
}
OUTPUT:
RETVAL
#IOCTL
######
SV*
ioctl(fd, request, arg)
SV *fd
unsigned long request
int arg
ALIAS: sysioctl=1
INIT:
CODE:
RETVAL=&PL_sv_undef;
//NOTE: Remember to add 1 to no error return
OUTPUT:
RETVAL
#if defined(IO_FD_OS_DARWIN)|| defined(IO_FD_OS_BSD)
#define IO_FD_ATIME atime=buf.st_atimespec.tv_sec+buf.st_atimespec.tv_nsec*1e-9;
#define IO_FD_MTIME mtime=buf.st_mtimespec.tv_sec+buf.st_mtimespec.tv_nsec*1e-9;
#define IO_FD_CTIME ctime=buf.st_ctimespec.tv_sec+buf.st_ctimespec.tv_nsec*1e-9;
#endif
#if defined(IO_FD_OS_LINUX)
#define IO_FD_ATIME atime=buf.st_atim.tv_sec+buf.st_atim.tv_nsec*1e-9;
#define IO_FD_MTIME mtime=buf.st_mtim.tv_sec+buf.st_mtim.tv_nsec*1e-9;
#define IO_FD_CTIME ctime=buf.st_ctim.tv_sec+buf.st_ctim.tv_nsec*1e-9;
#endif
#if defined(IO_FD_OS_DARWIN)
#define DEV_FMT "%d"
#else
#define DEV_FMT "%lld"
#endif
void
stat(target)
SV *target;
ALIAS:
IO::FD::stat = 1
IO::FD::lstat = 2
INIT:
int ret=-1;
char *path;
struct stat buf;
int len;
long long atime;
long long mtime;
long long ctime;
char scratch[32]; //
SV *tmp;
PPCODE:
if(SvOK(target) && SvIOK(target)){
//Integer => always an fstat
ret=fstat(SvIV(target), &buf);
}
else if(SvOK(target)&& SvPOK(target)){
//String => stat OR lstat
len=SvCUR(target);
Newx(path, len+1, char); //Allocate plus null
Copy(SvPVbyte_nolen(target), path, len, char); //Copy
path[len]='\0'; //set null
switch(ix){
case 1:
ret=stat(path, &buf);
break;
case 2:
ret=lstat(path, &buf);
break;
default:
break;
}
Safefree(path);
}
else {
//Unkown
}
//fprintf(stderr, "Size of dev: %d\n",sizeof(buf.st_dev));
//fprintf(stderr, "Size of ino: %d\n",sizeof(buf.st_ino));
//fprintf(stderr, "Size of nlink: %d\n",sizeof(buf.st_nlink));
//fprintf(stderr, "Size of size: %d\n",sizeof(buf.st_size));
//fprintf(stderr, "Size of blocks: %d\n",sizeof(buf.st_blocks));
if(ret>=0){
switch(GIMME_V){
case G_ARRAY:
IO_FD_ATIME
IO_FD_MTIME
IO_FD_CTIME
//Work through the items in the struct
//
EXTEND(SP, 13); //macos bsd linux
// ====== st_dev
if(buf.st_dev<0){
// Handle signed value
//int32 uint64 uint64
if(sizeof(IV)<sizeof(buf.st_dev)){
//sprintf(scratch,"%lld", buf.st_dev);
sprintf(scratch, DEV_FMT, buf.st_dev);
tmp = newSVpv(scratch,0);
}
else{
tmp=newSViv(buf.st_dev);
}
}
else {
// Handle unsigned value
if(sizeof(UV)<sizeof(buf.st_dev)){
//sprintf(scratch,"%llu", buf.st_dev);
sprintf(scratch, DEV_FMT, buf.st_dev);
tmp = newSVpv(scratch,0);
}
else{
tmp=newSVuv(buf.st_dev);
}
}
mPUSHs(tmp);
// ==== st_ino
if(sizeof(UV)<sizeof(buf.st_ino)){
sprintf(scratch,"%llu", buf.st_ino);
tmp = newSVpv(scratch,0);
}
else{
tmp=newSVuv(buf.st_ino);
}
mPUSHs(tmp);
//mPUSHs(newSVuv(buf.st_ino)); //uint32/64 uint64 uint32/uint64
// ==== st_mode
mPUSHs(newSVuv(buf.st_mode)); //uint16 uint16 uint32
//
// ==== st_nlink
if(sizeof(UV)<sizeof(buf.st_nlink)){
// We know we are longer than 32 bits
//sprintf(scratch,"%llu", buf.st_nlink);
sprintf(scratch, DEV_FMT, buf.st_nlink);
tmp = newSVpv(scratch,0);
}
else{
tmp=newSVuv(buf.st_nlink);
}
mPUSHs(tmp);
//mPUSHs(newSVuv(buf.st_nlink));//uint16 uint64 uint32
// ==== st_uid
mPUSHs(newSVuv(buf.st_uid)); //uint32 uint32 uint32
//
// ==== st_gid
mPUSHs(newSVuv(buf.st_gid)); //uint32 uint32 uint32
//
// ==== st_rdev
if(buf.st_rdev<0){
// Handle signed value
//int32 uint64 uint64
if(sizeof(IV)<sizeof(buf.st_rdev)){
//sprintf(scratch,"%lld", buf.st_rdev);
sprintf(scratch, DEV_FMT, buf.st_rdev);
tmp = newSVpv(scratch,0);
}
else{
tmp=newSViv(buf.st_rdev);
}
}
else {
// Handle unsigned value
if(sizeof(UV)<sizeof(buf.st_rdev)){
//sprintf(scratch,"%llu", buf.st_rdev);
sprintf(scratch,DEV_FMT, buf.st_rdev);
tmp = newSVpv(scratch,0);
}
else{
tmp=newSVuv(buf.st_rdev);
}
}
mPUSHs(tmp);
// ==== st_size
if(sizeof(IV)<sizeof(buf.st_size)){
sprintf(scratch,"%lld", buf.st_size);
tmp = newSVpv(scratch,0);
}
else{
tmp=newSViv(buf.st_size);
}
mPUSHs(tmp);
//mPUSHs(newSViv(buf.st_size)); //int64 int64 int64
// ==== Times
if(sizeof(IV)<sizeof(atime)){
sprintf(scratch,"%lld", atime);
tmp = newSVpv(scratch,0);
mPUSHs(tmp);
sprintf(scratch,"%lld", mtime);
tmp = newSVpv(scratch,0);
mPUSHs(tmp);
sprintf(scratch,"%lld", ctime);
tmp = newSVpv(scratch,0);
mPUSHs(tmp);
}
else{
// ==== st_atime
mPUSHs(newSViv(atime));
// ==== st_mtime
mPUSHs(newSViv(mtime));
// ==== st_ctime
mPUSHs(newSViv(ctime));
}
// ==== st_blksize
mPUSHs(newSViv(buf.st_blksize));//int32 int32 int32
// ==== st_blocks
if(sizeof(IV)<sizeof(buf.st_blocks)){
sprintf(scratch,"%lld", buf.st_blocks);
tmp = newSVpv(scratch,0);
}
else{
tmp=newSViv(buf.st_blocks);
}
mPUSHs(tmp);
//mPUSHs(newSViv(buf.st_blocks));//int64 int64 int32
XSRETURN(13);
break;
case G_VOID:
XSRETURN_EMPTY;
break;
case G_SCALAR:
default:
mXPUSHs(newSViv(1));
XSRETURN(1);
break;
}
}
switch(GIMME_V){
case G_SCALAR:
mXPUSHs(&PL_sv_undef);
XSRETURN(1);
break;
case G_VOID:
case G_ARRAY:
default:
XSRETURN_EMPTY;
break;
}