#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
#include <stdhdrs.h>
#include <strbuf.h>
#include <error.h>
#include "fileio.h"
#include "msgjrep.h"
#include "position.h"
#include "err.h"
#ifdef OS_FREEBSD
#define O_SYNC O_FSYNC
#endif
#define BUFSIZE 32
void Position::SetName( const char *journal, StrPtr *ival )
{
name.Set( journal );
name.Append( ".position" );
if( ival )
{
name.Append( "." );
name.Append( ival );
}
}
void Position::SetOffset( off_tL soffset )
{
offset = soffset;
}
char *Position::GetName()
{
return name.Text();
}
off_tL Position::GetOffset()
{
return offset;
}
bool Position::Init( const char *journal, StrPtr *ival, Error *e )
{
SetName( journal, ival );
return true;
}
bool Position::Open( Error *e )
{
if( ( positionfd = open( GetName(),
O_RDWR | O_CREAT | O_SYNC, S_IRUSR | S_IWUSR ) ) == -1 )
return syserr( "open", GetName(), e );
return true;
}
bool Position::Seek( off_t poffset, const char *op, Error *e )
{
if( lseek( positionfd, poffset, SEEK_SET ) == -1 )
return syserr( op, GetName(), e );
return true;
}
bool Position::Read( Error *e )
{
ssize_t n;
char buf[ BUFSIZE ];
ssize_t len;
if( !Seek( 0, "read seek", e ) )
return false;
if( ( n = read( positionfd, buf, BUFSIZE - 1 ) ) == -1 )
return syserr( "read", GetName(), e );
if( n )
{
/*
* Don't include the newline character (if present) in the
* string length of the offset read from the position file.
*/
len = n - 1;
if( buf[ len ] != '\n' )
len++;
buf[ len ] = '\0';
if( strspn( buf, "0123456789" ) != len )
{
e->Set( MsgJrep::PosBadChars ) << GetName();
return false;
}
if( !sscanf( buf, off_t_formatL, &offset ) )
{
e->Set( MsgJrep::PosSscanfFail ) << GetName();
return false;
}
}
else
{
offset = 0;
}
return true;
}
bool Position::Increment( off_tL increment, Error *e )
{
offset += increment;
return true;
}
bool Position::Write( Error *e )
{
char buf[ BUFSIZE ];
int len;
if( !Seek( 0, "write seek", e ) )
return false;
sprintf( buf, off_t_formatL, offset );
len = strlen( buf );
buf[ len++ ] = '\n';
if( write( positionfd, buf, len ) == -1 )
return syserr( "write", GetName(), e );
return true;
}
bool Position::Truncate( Error *e )
{
if( ftruncate( positionfd, 0 ) == -1 )
return syserr( "truncate", GetName(), e );
return true;
}
bool Position::Close( Error *e )
{
if( close( positionfd ) == -1 )
return syserr( "close", GetName(), e );
return true;
}