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

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

//<file>
//
// Name:       lfilestat.h
//
// Purpose:    Interface to function lstat
//
// Created:    07 Jan 1997 Bruno Reisinger
//
// Description:
//
// $Id: lfilestat.h,v 1.1 1997/01/07 10:18:20 breising Exp $
//
//</file>
// 
// $Log: lfilestat.h,v $
// Revision 1.1  1997/01/07 10:18:20  breising
// Initial revision
//

#ifndef hg_utils_lfilestat_h
#define hg_utils_lfilestat_h
 
#include "hgunistd.h"
#include <sys/stat.h>
#include "types.h"
#include "str.h"

//<class>
//
// Name:       LFileStat
//
// Purpose:    Interface to function stat
//
//
// Public Interface:
//
// - LFileStat()
//   Constructor.
//   
// - boolean load( const RString& file)
//   Calls 'stat' for file and stores the retrieved values.
//   Method returns false on 'stat' errors or if the file doesn't exist.
//   
// - 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 isLnk()
//   Returns true if the loaded file is a symbolic link
//
// - 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 exist( const RString& file)
//   Returns true if file exists.
//   
// - 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 LFileStat {
  public:
     LFileStat();

     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 isLnk() 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 exist( const RString& name);
     static boolean which( const RString& name, RString& fullName);

  private:
     boolean loaded_;
     struct stat buf_;
     static LFileStat fileStat_;

  public:
    static const char* version1_1;

};

static const char* LFileStat_version = LFileStat::version1_1;

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

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

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

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

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

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

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

inline boolean LFileStat::isLnk() const {
     return S_ISLNK( buf_.st_mode);
}

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

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

inline boolean LFileStat::suid() const
{
#ifdef WIN32
  return S_ISUID(buf_.st_mode);
#else
  return buf_.st_mode & S_ISUID;
#endif
}

inline boolean LFileStat::sgid() const
{
#ifdef WIN32
  return S_ISGID(buf_.st_mode);
#else
  return buf_.st_mode & S_ISGID;
#endif
}

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

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

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

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

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

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

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

inline boolean LFileStat::exist( const RString& name) {
     return (fileStat_.load( name));
}

#endif





