// This may look like C code, but it is really -*- C++ -*-

// <copyright>
// 
// Copyright (c) 1993-1995
// Institute for Information Processing and Computer Supported New Media (IICM),
// Graz University of Technology, Austria.
// 
// </copyright>

//<file>
//
// Name:       filestat.h
//
// Purpose:    Interface to function stat
//
// Created:    18 Nov 94    Gerald Pani
//
// Description:
//
//</file>


#ifndef hg_utils_filestat_h
#define hg_utils_filestat_h
 
#include <hyperg/utils/hgunistd.h>
#include <sys/stat.h>
#include <hyperg/utils/types.h>
#include <hyperg/utils/str.h>

//<class>
//
// Name:       FileStat
//
// Purpose:    Interface to function stat
//
//
// Public Interface:
//
// - FileStat()
//   Constructor.
//   
// - boolean load( const RString& file)
//   Calls 'stat' for file and stores the retrieved values.
//   Method returns false on 'stat' errors.
//   
// - boolean execute()
//   Returns true if the current user has execute permissions for the loaded file.
//   
// - boolean readable()
//   Returns true if the loaded file is readable for the current user.
//   
// - boolean writeable()
//   Returns true if the loaded file is writeable for the current user.
//   
// - boolean isDir()
//   Returns true if the loaded file is a directory.
//   
// - boolean isChr()
//   Returns true if the loaded file is a character special file.
//   
// - boolean isBlk()
//   Returns true if the loaded file is a block special file.
//   
// - boolean isReg()
//   Returns true if the loaded file is a regular file.
//   
// - boolean isFifo()
//   Returns true if the loaded file is a FIFO.
//   
// - boolean suid()
//   Returns true if the loaded file has the set user id bit set.
//   
// - boolean sgid()
//   Returns true if the loaded file has the set group id bit set.
//   
// - uid_t uid()
//   Returns the user id of the file loaded.
//   
// - gid_t gid()
//   Returns the group id of the file loaded.
//   
// - off_t size()
//   Returns the size of the file loaded.
//   
// - time_t access()
//   Returns the last access time of the file loaded.
//   
// - time_t modified()
//   Returns the last modification time of the file loaded.
//   
// - time_t statusChange()
//   Returns the last status change time of the file loaded.
//   
// - long blockSize()
//   Returns the used block size.
//   
// - long blocks()
//   Returns the number of used blocks for the file loaded.
//   
// - const struct stat& buffer()
//   Returns a reference to the internal stat buffer.
//   
// - static boolean executable( const RString& file)
//   Returns true if file is executable for the current user.
//   
// - static boolean which( const RString& file, RString& fullFileName)
//   Returns true if file is found via the actual search path and
//   executable for the current user. The full file name of this executable
//   is returned in fullFileName.
//   
// 
// Description:
//
//
//</class>

class FileStat {
  public:
     FileStat();

     boolean load( const RString& name);

     boolean execute() const;
     boolean readable() const;
     boolean writable() const;

     boolean isDir() const;
     boolean isChr() const;
     boolean isBlk() const;
     boolean isReg() const;
     boolean isFifo() const;

     boolean suid() const;
     boolean sgid() const;
     
     uid_t uid() const;
     gid_t gid() const;
     off_t size() const;
     time_t access() const;
     time_t modified() const;
     time_t statusChange() const;
     long blockSize() const;
     long blocks() const;

     const struct stat& buffer() const;

     static boolean executable( const RString& name);
     static boolean which( const RString& name, RString& fullName);

  private:
     boolean loaded_;
     struct stat buf_;
     static FileStat fileStat_;
};

inline FileStat::FileStat() : loaded_(false) {}

inline boolean FileStat::load( const RString& name) {
     if (!::stat( name, &buf_))
	  loaded_ = true;
     else
	  loaded_ = false;
     return loaded_;
}

inline const struct stat& FileStat::buffer() const {
     return buf_;
}

inline boolean FileStat::isDir() const {
     return S_ISDIR( buf_.st_mode);
}

inline boolean FileStat::isChr() const {
     return S_ISCHR( buf_.st_mode);
}

inline boolean FileStat::isBlk() const {
     return S_ISBLK( buf_.st_mode);
}

inline boolean FileStat::isReg() const {
     return S_ISREG( buf_.st_mode);
}

inline boolean FileStat::isFifo() const {
     return S_ISFIFO( buf_.st_mode);
}

inline uid_t FileStat::uid() const {
     return buf_.st_uid;
}

inline gid_t FileStat::gid() const {
     return buf_.st_gid;
}

inline boolean FileStat::suid() const {
     return buf_.st_mode & S_ISUID;
}

inline boolean FileStat::sgid() const {
     return buf_.st_mode & S_ISGID;
}

inline off_t FileStat::size() const {
     return buf_.st_size;
}

inline time_t FileStat::access() const {
     return buf_.st_atime;
}

inline time_t FileStat::modified() const {
     return buf_.st_mtime;
}

inline time_t FileStat::statusChange() const {
     return buf_.st_ctime;
}

inline long FileStat::blockSize() const {
     return buf_.st_blksize;
}

inline long FileStat::blocks() const {
     return buf_.st_blocks;
}

inline boolean FileStat::executable( const RString& name) {
     return (fileStat_.load( name) && fileStat_.isReg() && fileStat_.execute());
}

#endif





