// 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__