/*
	$Id: CFile.h,v 1.1 2003/04/20 23:29:40 dasenbro Exp $

	File:		CFile.h

	Contains:	Mac OS versions of fstreams that use Async file system calls.
				So created so provide identical CDatabase code base for Mac OS
				and Rhapsody.

	Version:	Apple Mail Server - Mac OS X :  $Revision: 1.1 $

	Written by:	Chris Jalbert

	Copyright:	© 1996-2001 by Apple Computer, Inc., all rights reserved.

 	NOT_FOR_OPEN_SOURCE <to be reevaluated at a later time>

	Change History:

		$Log: CFile.h,v $
		Revision 1.1  2003/04/20 23:29:40  dasenbro
		Initial check-in.
		
		Revision 1.18  2002/07/16 01:16:34  dasenbro
		Added better handling of missing data files.
		
		Revision 1.17  2002/05/09 16:59:04  dasenbro
		Changed all str... calls to CUtils::Str... to be NULL safe.
		
		Revision 1.16  2002/04/18 18:09:16  dasenbro
		Changed bool to Bool for word alignment.
		
		Revision 1.15  2002/04/18 17:09:32  dasenbro
		Changed Bool to Bool in structs for word alingnment.
		
		Revision 1.14  2002/04/15 21:29:16  dasenbro
		Added eFilePermissions consts for setting file permissions.
		
		Revision 1.13  2002/03/21 16:41:46  dasenbro
		Updated file version information.
		
		Revision 1.12  2002/03/05 20:41:28  dasenbro
		Updated for gcc3.
		
		Revision 1.11  2002/02/20 20:40:50  dasenbro
		gcc3 changes.
		
		Revision 1.10  2002/01/23 22:49:19  dasenbro
		Added file locking members.
		
		Revision 1.9  2002/01/14 17:05:05  dasenbro
		Initial S4 updates.
		
		Revision 1.8  2001/06/21 20:43:14  dasenbro
		Added Change History.
		

	Projector History:

		 <1>	04/07/98	CPJ		Initial breakout.

	To Do:
*/


#ifndef __CFile_h__
#define __CFile_h__	1

#include "MailTypes.h"

#include <unistd.h>		// for sync()
#include <limits.h>		// for PATH_MAX
#include <stdio.h>		// for PATH_MAX, FILE, fopen(), etc.

class ios
{
	public:
		ios ( void );
	   ~ios ( void );

		enum seek_dir { beg, cur, end};
};

typedef size_t	streamsize;
typedef size_t	streamoff;
typedef ios		ios_base;

static FILE	* const		kBadFileRef = NULL;
static const sInt32		kMaxFiles	= 5;

typedef char	CFileSpec[ PATH_MAX ];
typedef char   *CFileSpecPtr;

#define		kRollLogMessageStartStr	"-- Start: Server rolled log on: %s --\n"
#define		kRollLogMessageEndStr	"-- End: Server rolled log on: %s --\n"
#define		kMemFullErrStr			"*** Error:  Could not roll file, memory full ***\n"
#define		kRenameErrorStr			"*** Error:  Received error %d during rename ***\n"

typedef enum {
	k700		= 0100700,
	k755		= 0100755,
	k600		= 0100600,
	k644		= 0100644
} eFilePermissions;

class CFile
{
public:
				CFile	( void )	throw();
				CFile	( const char *inFilePath, const eFilePermissions inPerm, Boolean inCreate = true ) throw( OSErr );
				CFile	( const char *inFilePath, const Bool inCreate, const Bool inRoll )	throw( OSErr );
				CFile	( const char *inFilePath, const uInt32 inUID, const uInt32 inGID, const uInt32 inPerm ) throw( OSErr );
	virtual	   ~CFile	( void );

	virtual	void open	( const char *inFileSpec, const Boolean inCreate = false )	throw( OSErr );

	// filesystem operations
	virtual	sInt64		freespace	( void ) const	throw( OSErr );
	virtual	void		syncdisk	( void ) const	throw();

	virtual	int			is_open		( void ) const	throw();
	virtual	CFile&		seteof		( sInt64 lEOF )	throw( OSErr );
	virtual	CFile&		flush		( void )		throw( OSErr );
	virtual	void		close		( void )		throw( OSErr );
	virtual	int			Lock		( void )		throw( OSErr );
	virtual	int			LockNoBlock	( void )		throw( OSErr );
	virtual	int			WaitLock	( void )		throw( OSErr );

	// block io
	virtual	ssize_t	ReadBlock		( void *s, streamsize n )					throw( OSErr );
	virtual	CFile&	Read			( void *s, streamsize n )					throw( OSErr );
			CFile&	read			( char *s, streamsize n )					throw( OSErr );
			CFile&	read			( unsigned char *s, streamsize n )			throw( OSErr );
			CFile&	read			( signed char *s, streamsize n )			throw( OSErr );

	virtual	CFile& write			( const void *s, streamsize n )				throw( OSErr );
			CFile& write			( const char *s, streamsize n )				throw( OSErr );
			CFile& write			( const unsigned char *s, streamsize n )	throw( OSErr );
			CFile& write			( const signed char *s, streamsize n )		throw( OSErr );

	// positioning
	virtual	CFile&	seekg		( sInt64 lOffset, ios::seek_dir mark = ios::beg )	throw( OSErr );
	virtual	sInt64	tellg		( void )	throw( OSErr );

	virtual	CFile&	seekp		( sInt64 lOffset, ios::seek_dir = ios::beg )			throw( OSErr );
	virtual	sInt64	tellp		( void )	throw( OSErr );

	virtual	sInt64	FileSize	( void )	throw( OSErr );

protected:
	char		   *fFilePath;
	FILE		   *fFileRef;
	uTime_t			fOpenTime;
	uTime_t			fLastChecked;
	Bool			fRollLog;
	sInt64			fReadPos;
	sInt64			fWritePos;
	Bool			fReadPosOK;
	Bool			fWritePosOK;
};

inline CFile& CFile::flush ( void ) throw( OSErr )
#if USE_UNIXIO
{ return *this; }	// A no-op, because I'm using unbuffered I/O.
#else
{ ::fflush ( fFileRef ); return *this; }
#endif

inline CFile&	CFile::read	 ( char *s, streamsize n )					throw( OSErr ) { return this->Read( (void *)s, n ); }
inline CFile&	CFile::read	 ( unsigned char *s, streamsize n )			throw( OSErr ) { return this->Read( (void *)s, n ); }
inline CFile&	CFile::read	 ( signed char *s, streamsize n )			throw( OSErr ) { return this->Read( (void *)s, n ); }
inline CFile&	CFile::write ( const char *s, streamsize n )			throw( OSErr ) { return this->write( (void *)s, n ); }
inline CFile&	CFile::write ( const unsigned char *s, streamsize n )	throw( OSErr ) { return this->write( (void *)s, n ); }
inline CFile&	CFile::write ( const signed char *s, streamsize n )		throw( OSErr ) { return this->write( (void *)s, n ); }
inline sInt64	CFile::tellg ( void )									throw( OSErr ) { return( fReadPos ); }
inline sInt64	CFile::tellp ( void )									throw( OSErr ) { return( fWritePos ); }

#endif	// __CFile_h__
