/***************************************************************************
 $RCSfile: file.h,v $
 -------------------
 cvs         : $Id: file.h,v 1.7 2003/04/08 09:38:01 aquamaniac Exp $
 begin       : Fri Dec 14 2001
 copyright   : (C) 2001 by Martin Preuss
 email       : martin@aquamaniac.de
 */


/***************************************************************************
 *                                                                         *
 *   This library is free software; you can redistribute it and/or         *
 *   modify it under the terms of the GNU Lesser General Public            *
 *   License as published by the Free Software Foundation; either          *
 *   version 2.1 of the License, or (at your option) any later version.    *
 *                                                                         *
 *   This library is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
 *   Lesser General Public License for more details.                       *
 *                                                                         *
 *   You should have received a copy of the GNU Lesser General Public      *
 *   License along with this library; if not, write to the Free Software   *
 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston,                 *
 *   MA  02111-1307  USA                                                   *
 *                                                                         *
 ***************************************************************************/


#ifndef C_FILE_H
#define C_FILE_H


#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <dirent.h>
#include <unistd.h>

#include <openhbci/datetime.h>
#include <openhbci/error.h>

typedef int t_hFILE;
typedef off_t t_offset;


// access modes
#define FILE_AM_RDONLY            0x0001
#define FILE_AM_WRONLY            0x0002
#define FILE_AM_RDWR              0x0004
#define FILE_AM_APPEND            0x0008

#define FILE_INTERNAL_AM_MASK     0x00f0
#define FILE_AM_OPEN_EXISTING     0x0000
#define FILE_AM_CREATE_NEW        0x0010
#define FILE_AM_TRUNCATE_EXISTING 0x0020
#define FILE_AM_OPEN_ALWAYS       0x0030
#define FILE_AM_CREATE_ALWAYS     0x0040

// for the access method
#define FILE_ACCESS_READ R_OK
#define FILE_ACCESS_WRITE W_OK
#define FILE_ACCESS_RW (R_OK | W_OK)
#define FILE_ACCESS_EXEC X_OK
#define FILE_ACCESS_EXIST F_OK

// creation modes
#define FILE_CM_WRITE S_IWUSR
#define FILE_CM_READ S_IRUSR
#define FILE_CM_EXEC S_IXUSR

#define FILE_CM_GROUP_WRITE S_IWGRP
#define FILE_CM_GROUP_READ S_IRGRP
#define FILE_CM_GROUP_EXEC S_IXGRP

#define FILE_CM_OTHER_WRITE S_IWOTH
#define FILE_CM_OTHER_READ S_IROTH
#define FILE_CM_OTHER_EXEC S_IXOTH

// lcoking modes
#define FILE_LOCK_SHARED    1
#define FILE_LOCK_EXCLUSIVE 2

// whence values
#define FILE_WHENCE_EXACT   SEEK_SET
#define FILE_WHENCE_CURRENT SEEK_CUR
#define FILE_WHENCE_END     SEEK_END

// Some macros
#define m_FILE_IS_DIR(m) S_ISDIR(m)
#define m_FILE_IS_FILE(m) S_ISREG(m)
#define m_FILE_IS_LINK(m) S_ISLNK(m)
#define m_FILE_IS_FIFO(m) S_ISFIFO(m)
#define m_FILE_IS_SOCKET(m) S_ISSOCK(m)

// Error codes
#define FILE_NO_FILEHANDLE -1


namespace HBCI {

/**
 *
 */
typedef struct {
  unsigned long size;
  unsigned int mode;
  DateTime atime;   // time of last access
  DateTime mtime;   // time of last modification
  DateTime ctime;   // time of last change
} DLLIMPORT s_filestat;



/**
 * @short Platform independent handling of files.
 */
class DLLIMPORT File {
private:
  string _name;
  t_hFILE _handle;

  void _convPath(string &p);

public:
  DLLIMPORT typedef enum {
    StdTypeStdIn=0,
    StdTypeStdOut,
    StdTypeStdErr
  } StdType;

  File(): _name(""),_handle(FILE_NO_FILEHANDLE){
  };

  File(const string &name);
  File(StdType typ);


  ~File();

  void operator=(File &f);

  /**
   * Returns the file name.
   */
  const string &name() const { return _name;};

  /**
   * Checks if the given file may be accessed in the specified way.
   * @return true if access possible, false otherwise
   * @param mode the access mode to check for.
   * Possible values are FILE_ACCESS_READ/-WRITE/-EXEC/-EXIST/-RW
   */
  Error accessFile(int mode);

  /**
   * Opens the given file. Depending on "mode" this file can be created
   * using this file.
   * @return handle to the file (on error FILE_NO_FILEHANDLE)
   * @param access tells what you want to do with the file (
   * FILE_AM_RDONLY, FILE_AM_WRONLY, FILE_AM_RDWR, FILE_AM_APPEND,
   * FILE_AM_CREATE, FILE_AM_TRUNCATE, FILE_AM_EXCLUSICE)
   * @param mode if the file has to be created: the mode of the new file (
   * FILE_CM_WRITE, FILE_CM_READ, FILE_CM_EXEC, FILE_CM_GROUP_WRITE,
   * FILE_CM_GROUP_READ, FILE_CM_GROUP_EXEC, FILE_CM_OTHER_WRITE,
   * FILE_CM_OTHER_READ, FILE_CM_OTHER_EXEC). Please note that on some
   * systems (especially Windoze/BeOS) not all of the modes are available.
   */
  Error openFile(int access,
		 int mode=FILE_CM_WRITE | FILE_CM_READ);

  /**
   * Closes an open file.
   * @return true if ok, false on error.
   */
  Error closeFile();

  /**
   * Creates the given file.
   * @return handle to the file (on error FILE_NO_FILEHANDLE)
   * @param access tells what you want to do with the file (
   * FILE_AM_RDONLY, FILE_AM_WRONLY, FILE_AM_RDWR, FILE_AM_APPEND,
   * FILE_AM_CREATE, FILE_AM_TRUNCATE, FILE_AM_EXCLUSICE)
   * @param mode if the file has to be created: the mode of the new file (
   * FILE_CM_WRITE, FILE_CM_READ, FILE_CM_EXEC, FILE_CM_GROUP_WRITE,
   * FILE_CM_GROUP_READ, FILE_CM_GROUP_EXEC, FILE_CM_OTHER_WRITE,
   * FILE_CM_OTHER_READ, FILE_CM_OTHER_EXEC). Please note that on some
   * systems (especially Windoze/BeOS) not all of the modes are available.
   */
  Error createFile(int access,
		   int mode=FILE_CM_WRITE | FILE_CM_READ);

  /**
   * Retrieves information about the given file.
   * @return false on error, true otherwise
   * @param s reference to a buffer to hold the data retrieved
   */
  Error statFile(s_filestat &s);

  /**
   * Renames the given file. Even if the underlying os allows moving
   * files/dirs across directories this method does not guarantee that
   * feature. Using this feature might lead to incompatibilities !
   * @return true if ok, false on error
   * @param newname new path and name
   */
  Error renameFile(string newname);

  /**
   * Deletes the given file.
   * @return true if ok, false on error
   */
  Error deleteFile();

  /**
   * Tries to lock areas of an open file.
   * @return true if ok, false on error
   * @param mode how to lock the file (FILE_LOCK_SHARED, FILE_LOCK_EXCLUSIVE)
   * @param whence how to interprete the start parameter
   * (FILE_WHENCE_EXACT, FILE_WHENCE_CURRENT, FILE_WHENCE_END)
   * @param start beginning of the area to lock
   * @param length number of bytes to lock (0=follow EOF)
   * @param wait true: make this method blocking (wait until the lock can
   * be set), false:immediately return if the lock could not be applied.
   * Please notice that on WIN95/WIN3 this flag must be set to false !
   */
  Error lockFile(int mode,
                   int whence,
                   t_offset start,
                   t_offset length,
                   bool wait);

  /**
   * Tries to unlock areas of an open file. The parameters to this method
   * MUST match those to the corresponding "lock"!
   * @return true if ok, false on error
   * @param whence how to interprete the start parameter
   * (FILE_WHENCE_EXACT, FILE_WHENCE_CURRENT, FILE_WHENCE_END)
   * @param start beginning of the area to lock
   * @param length number of bytes to lock (0=follow EOF)
   */
  Error unlockFile(int whence,
                     t_offset start,
                     t_offset length);

  /**
   * Retrieves the current position of the file pointer.
   * @return true if ok, false otherwise
   * @param p reference to a variable that is to hold the pointer
   */
  Error filePos(t_offset &p);

  /**
   * Sets the file pointer of an open file
   * @param p new file position (interpreted according to "whence")
   * @param whence how to interprete the file position
   * (FILE_WHENCE_EXACT, FILE_WHENCE_CURRENT, FILE_WHENCE_END)
   */
  Error setFilePos(t_offset p, int whence);

  /**
   * Sets a new mode for the given file.
   * @return true if ok, false otherwise
   * @param mode to be set (FILE_CM_WRITE, FILE_CM_READ, FILE_CM_EXEC,
   * FILE_CM_GROUP_WRITE, FILE_CM_GROUP_READ, FILE_CM_GROUP_EXEC,
   * FILE_CM_OTHER_WRITE, FILE_CM_OTHER_READ, FILE_CM_OTHER_EXEC).
   * Please note that on some systems (especially Windoze/BeOS) not all of
   * the modes are available.
   */
  Error changeMode(int mode);

  /**
   * Reads data from an open file.
   * @return number of bytes read (-1 on error)
   * @param data pointer to a buffer to receive the data
   * @param size size of the buffer
   */
  Error readData(string &data, unsigned int size);

  /**
   * Write data to an open file.
   * @return number of bytes written (-1 on error)
   * @param buffer pointer to a buffer that holds the data to be written
   */
  Error writeData(const string &buffer);


};


} /* namespace HBCI */



#endif





