// FileStat.h
// 12/16/97
#ifndef __FILE_STAT_H__
#define __FILE_STAT_H__
#pragma interface "FileStat.h"
#ifndef __BASIC_TYPES__
#define __BASIC_TYPES__
typedef int Integer32;
typedef Integer32 SizeType;
typedef Integer32 OffsetType;
typedef Integer32 CounterType;
typedef Integer32 ArenaID;
typedef Integer32 EntryID;
typedef Integer32 BoolType;
enum { True = 1, False = 0 };
typedef Integer32 ComparisonType;
enum { GreaterThan = 1, EqualTo = 0, LessThan = -1 };
typedef void *PointerType;
#endif // __BASIC_TYPES__
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <dirent.h>
#include <Regex.h>
#include <stdlib.h>
// Wrapper class for stat() system call
class FileStat {
protected:
char *path;
enum FileStatus {
Found, NotFound
} status;
struct stat st;
uid_t uid;
gid_t gid;
public:
FileStat(const char *p = 0) {
if (p == 0) {
path = 0;
status = NotFound;
return;
}
path = new char[strlen(p) + 1];
strcpy(path, p);
if (stat(path, &st) != 0) {
status = NotFound;
return;
} else {
status = Found;
uid = geteuid();
gid = getegid();
}
}
~FileStat() {
if (path)
delete path;
}
BoolType restat() {
if (path == 0 || stat(path, &st) != 0) {
status = NotFound;
return False;
} else {
status = Found;
return True;
}
}
inline BoolType exists() {
return status == Found;
}
inline BoolType isRegularFile() {
return status == Found && S_ISREG(st.st_mode);
}
inline BoolType isDirectory() {
return status == Found && S_ISDIR(st.st_mode);
}
inline BoolType isCharacterDevice() {
return status == Found && S_ISCHR(st.st_mode);
}
inline BoolType isBlockDevice() {
return status == Found && S_ISBLK(st.st_mode);
}
inline BoolType isFIFO() {
return status == Found && S_ISFIFO(st.st_mode);
}
inline BoolType isSocket() {
return status == Found && S_ISSOCK(st.st_mode);
}
inline BoolType isLink() {
return status == Found && S_ISLNK(st.st_mode);
}
inline SizeType getSize() {
return status == Found ? (SizeType)st.st_size : 0;
}
BoolType isReadable() {
if (status == NotFound)
return False;
if (uid == st.st_uid) {
return (st.st_mode & S_IRUSR) == S_IRUSR;
} else if (gid == st.st_gid) {
return (st.st_mode & S_IRGRP) == S_IRGRP;
} else {
return (st.st_mode & S_IROTH) == S_IROTH;
}
}
BoolType isWritable() {
if (status == NotFound)
return False;
if (uid == st.st_uid) {
return (st.st_mode & S_IWUSR) == S_IWUSR;
} else if (gid == st.st_gid) {
return (st.st_mode & S_IWGRP) == S_IWGRP;
} else {
return (st.st_mode & S_IWOTH) == S_IWOTH;
}
}
BoolType isExecutable() {
if (status == NotFound)
return False;
if (uid == st.st_uid) {
return (st.st_mode & S_IXUSR) == S_IXUSR;
} else if (gid == st.st_gid) {
return (st.st_mode & S_IXGRP) == S_IXGRP;
} else {
return (st.st_mode & S_IXOTH) == S_IXOTH;
}
}
};
// Wrapper class for scandir() systemcall
// Regular expression is used for wildcard
class ScanDir : public FileStat {
protected:
SizeType number;
SizeType index;
SizeType entry;
struct dirent **namelist;
Regex wildcard;
public:
ScanDir(const char *p, const char *w) :
FileStat(p), entry(-1), wildcard(w ? w : "[^\\.].*") {
if (isDirectory() && isReadable() && isExecutable()) {
number = scandir(p, &namelist, 0, alphasort);
} else {
number = -1;
namelist = 0;
}
}
~ScanDir() {
if (namelist != 0) {
for (index = 0; index < number; index++) {
free(namelist[index]);
}
free(namelist);
}
}
SizeType entries() {
if (entry < 0) {
int i = index;
initFilter();
for (entry = 0; getNextEntry() != 0; entry++)
;
index = i;
}
return entry;
}
BoolType initFilter() {
index = 0;
return number >= 0 ? True : False;
}
const char *getNextEntry() {
if (index < 0 || number <= 0 || index >= number) return 0;
struct dirent *ent;
for (ent = 0; index < number; index++) {
ent = namelist[index];
int len = strlen(ent->d_name);
if (wildcard.match(ent->d_name, len) == len)
break;
}
if (index < number) {
index++;
return ent->d_name;
} else {
return 0;
}
}
};
// Wrapper class for low level file I/O
class RawFile : public FileStat {
protected:
int fileDesc;
public:
RawFile(const char *file) : FileStat(file) { fileDesc = -1; }
RawFile(int fd = 0, const char *file = 0): FileStat(file), fileDesc(fd) {}
inline int getFileDesc() {
return fileDesc;
}
int open(int flags = O_RDWR, mode_t mode = S_IRUSR | S_IWUSR) {
if (exists() && !isDirectory()) {
fileDesc = ::open(path, flags, mode);
restat();
return fileDesc;
} else {
return -1;
}
}
int create(mode_t mode = S_IRUSR | S_IWUSR) {
fileDesc = ::creat(path, mode);
restat();
return fileDesc;
}
int close() {
if (fileDesc >= 0) {
int retcode = ::close(fileDesc);
restat();
fileDesc = -1;
return retcode;
} else {
return -1;
}
}
SizeType read(void *buf, SizeType count) {
if (fileDesc >= 0 && buf != 0 && count >= 0) {
count = ::read(fileDesc, buf, count);
restat();
return count;
} else {
return -1;
}
}
SizeType write(const void *buf, SizeType count) {
if (fileDesc >= 0 && buf != 0 && count >= 0) {
count = ::write(fileDesc, buf, count);
restat();
return count;
} else {
return -1;
}
}
OffsetType seek(OffsetType off = 0, int whence = SEEK_SET) {
if (fileDesc >= 0) {
off = ::lseek(fileDesc, off, whence);
restat();
return off;
} else {
return -1;
}
}
};
#endif // __FILE_STAT_H__