/*#io
File ioDoc(
docCopyright("Steve Dekorte", 2002)
docLicense("BSD revised")
docCredits("Initial version contributed by Miles Egan.")
*/
#include "IoFile_stat.h"
#include "IoState.h"
#include "IoDate.h"
#include <errno.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#define DATA(self) ((IoFileData *)IoObject_dataPointer(self))
#ifndef lstat
#define lstat stat
#endif
#ifndef S_ISDIR
#define S_ISDIR(mode) ((mode & _S_IFDIR) != 0)
#endif
#ifndef S_ISFIFO
#define S_ISFIFO(mode) ((mode & _S_IFIFO) != 0)
#endif
#ifndef S_ISREG
#define S_ISREG(mode) ((mode & _S_IFREG) != 0)
#endif
#ifndef S_ISLNK
#define S_ISLNK(mode) (0)
#endif
#ifndef S_ISSOCK
#define S_ISSOCK(mode) (0)
#endif
#ifndef _POSIX_C_SOURCE
#define _POSIX_C_SOURCE
#endif
void IoFile_statInit(IoFile *self)
{
{
IoMethodTable methodTable[] = {
{"stat", IoFile_stat},
{"protectionMode", IoFile_protectionMode},
{"lastAccessDate", IoFile_lastAccessDate},
{"lastInfoChangeDate", IoFile_lastInfoChangeDate},
{"lastDataChangeDate", IoFile_lastDataChangeDate},
{"userId", IoFile_userId},
{"groupId", IoFile_groupId},
{"size", IoFile_statSize},
{"isDirectory", IoFile_isDirectory},
{"isPipe", IoFile_isPipe},
{"isLink", IoFile_isLink},
{"isRegularFile", IoFile_isRegularFile},
{"isSocket", IoFile_isSocket},
{"isUserExecutable", IoFile_isUserExecutable},
{NULL, NULL},
};
IoObject_addMethodTable_(self, methodTable);
}
}
struct stat *IoFile_statPointer(IoFile *self, IoObject *locals, IoMessage *m)
{
if (!DATA(self)->info)
{
IoFile_stat(self, locals, m);
}
return (struct stat *)DATA(self)->info;
}
IoObject *IoFile_stat(IoFile *self, IoObject *locals, IoMessage *m)
{
/*#io
docSlot("stat",
"Updates the receiver's meta info cache.")
*/
struct stat *statInfo;
if (!DATA(self)->info)
{
DATA(self)->info = malloc(sizeof(struct stat));
}
statInfo = DATA(self)->info;
/*
{
char p[256];
sprintf(p, "touch %s", DATA(self)->path);
system(p);
}
*/
if (stat(CSTRING(DATA(self)->path), (struct stat *)(DATA(self)->info)) != 0)
{
IoState_error_(IOSTATE, m, "unable to stat '%s': %s",
CSTRING(DATA(self)->path),
strerror(errno));
}
return self;
}
/* ---------------------------------- */
IoObject *IoFile_protectionMode(IoFile *self, IoObject *locals, IoMessage *m)
{
/*#io
docSlot("protectionMode",
"Returns a Number containing the protection mode
associated with the file's path.")
*/
return IONUMBER(IoFile_statPointer(self, locals, m)->st_mode);
}
#ifndef _POSIX_C_SOURCE
struct timeval timespec2timeval(struct timespec ts)
{
struct timeval tv;
tv.tv_sec = ts.tv_sec;
tv.tv_usec = ts.tv_nsec / 1000;
return tv;
}
#endif
struct timeval time_t2timeval(time_t ts)
{
struct timeval tv;
tv.tv_sec = ts;
tv.tv_usec = 0;
return tv;
}
IoObject *IoFile_lastAccessDate(IoFile *self, IoObject *locals, IoMessage *m)
{
/*#io
docSlot("lastAccessDate",
"Returns a Date object containing the last date and
time the file was accessed.")
*/
struct stat *s = IoFile_statPointer(self, locals, m);
#ifndef _POSIX_C_SOURCE
struct timeval tv = timespec2timeval(s->st_atimespec);
#else
struct timeval tv = time_t2timeval(s->st_atime);
#endif
return IoDate_newWithTimeval_(IOSTATE, tv);
}
IoObject *IoFile_lastInfoChangeDate(IoFile *self, IoObject *locals, IoMessage *m)
{
/*#io
docSlot("lastInfoChangeDate",
"Returns a Date object containing the last date and
time the file's meta info was changed.")
*/
struct stat *s = IoFile_statPointer(self, locals, m);
#ifndef _POSIX_C_SOURCE
struct timeval tv = timespec2timeval(s->st_ctimespec);
#else
struct timeval tv = time_t2timeval(s->st_ctime);
#endif
return IoDate_newWithTimeval_(IOSTATE, tv);
}
IoObject *IoFile_lastDataChangeDate(IoFile *self, IoObject *locals, IoMessage *m)
{
/*#io
docSlot("lastDataChangeDate",
"Returns a Date object containing the last date and
time the file's contents were changed.")
*/
struct stat *s = IoFile_statPointer(self, locals, m);
#ifndef _POSIX_C_SOURCE
struct timeval tv = timespec2timeval(s->st_mtimespec);
#else
struct timeval tv = time_t2timeval(s->st_mtime);
#endif
/*
struct gettv get_tv;
struct timezone timezone;
struct tm *t;
gettimeofday(&get_tv, &timezone);
printf("stattv.tv_sec = %i\n", tv.tv_sec);
printf("get_tv.tv_sec = %i\n", get_tv.tv_sec);
*/
return IoDate_newWithTimeval_(IOSTATE, tv);
}
IoObject *IoFile_userId(IoFile *self, IoObject *locals, IoMessage *m)
{
/*#io
docSlot("userId",
"Returns a Number containing the user id associated with the file's path.")
*/
return IONUMBER(IoFile_statPointer(self, locals, m)->st_uid);
}
IoObject *IoFile_groupId(IoFile *self, IoObject *locals, IoMessage *m)
{
/*#io
docSlot("groupId",
"Returns a Number containing the group id associated with the file's path.")
*/
return IONUMBER(IoFile_statPointer(self, locals, m)->st_gid);
}
IoObject *IoFile_statSize(IoFile *self, IoObject *locals, IoMessage *m)
{
/*#io
docSlot("statSize",
"Returns the file's size in bytes as a Number.")
*/
return IONUMBER(IoFile_statPointer(self, locals, m)->st_size);
}
/* ---------------------------------- */
IoObject *IoFile_isDirectory(IoFile *self, IoObject *locals, IoMessage *m)
{
/*#io
docSlot("isDirectory",
"Returns true if the receiver's path points to a directory, false otherwise.")
*/
return IOBOOL(self, S_ISDIR(IoFile_statPointer(self, locals, m)->st_mode));
}
IoObject *IoFile_isPipe(IoFile *self, IoObject *locals, IoMessage *m)
{
/*#io
docSlot("isPipe",
"Returns true if the receiver is a pipe, false otherwise.")
*/
return IOBOOL(self, S_ISFIFO(IoFile_statPointer(self, locals, m)->st_mode));
}
IoObject *IoFile_isLink(IoFile *self, IoObject *locals, IoMessage *m)
{
/*#io
docSlot("isLink",
"Returns true if the receiver's path points to a link, false otherwise.")
*/
struct stat buf;
if (lstat(CSTRING(DATA(self)->path), &buf) != 0)
{
IoState_error_(IOSTATE, m, "unable to stat '%s': %s",
CSTRING(DATA(self)->path),
strerror(errno));
}
return IOBOOL(self, S_ISLNK((&buf)->st_mode));
}
IoObject *IoFile_isRegularFile(IoFile *self, IoObject *locals, IoMessage *m)
{
/*#io
docSlot("isRegularFile",
"Returns true if the receiver's file descriptor is a regular file, false otherwise.")
*/
return IOBOOL(self, S_ISREG(IoFile_statPointer(self, locals, m)->st_mode));
}
IoObject *IoFile_isSocket(IoFile *self, IoObject *locals, IoMessage *m)
{
/*#io
docSlot("isSocket",
"Returns true if the receiver's file descriptor is a Socket, false otherwise.")
*/
return IOBOOL(self, S_ISSOCK(IoFile_statPointer(self, locals, m)->st_mode));
}
IoObject *IoFile_isUserExecutable(IoFile *self, IoObject *locals, IoMessage *m)
{
/*#io
docSlot("isUserExecutable",
"Returns true if the receiver is user group executable, false otherwise.")
*/
#ifdef ON_WINDOWS
return IOFALSE(self);
#else
mode_t mode = IoFile_statPointer(self, locals, m)->st_mode;
mode_t check = S_IXUSR;
return IOBOOL(self, mode & check);
#endif
}
syntax highlighted by Code2HTML, v. 0.9.1