next up previous contents index
Next: Main.cc Up: The Sources Previous: SortedTable.h

FileStat.h

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



Mori Tetsuya / t2y3141592@gmail.com