123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625 |
- /*
- JAMLIB - A JAM subroutine library
- Copyright (C) 1999 Björn Stenberg
- 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
- Changes made by Johan Billing 2000-04-16:
- - Changed source to use feof() instead of errno == EPASTEOF
- - Changed source to use structrw to read and write structures
- - Added JAM_AddEmptyMessage()
- - Added error messages JAM_NO_MESSAGE and JAM_CORRUPT_MSG for
- JAM_ReadMsgHeader()
- - #includes stdlib.h instead of malloc.h and memory.h
- - Fixed a bug that caused JAM_AddMessage() to fail when trying to
- add an empty message to the messagebase under Linux.
- Backported changes from JAMLIB 1.4.7 made by Johan Billing 2003-10-26
- - Fixed memory leaks that would occur if JAM_ReadMsgHeader() failed
- - Added JAM_DeleteMessage()
- Other changes made by Johan Billing 2003-10-26
- - Fixed comparison between signed and unsigned variable in JAM_AddMessage()
- - Improved handling of ActiveMsgs counter. JAM_AddMessage() now only
- increases ActiveMsgs if the added message does not have JAM_MSG_DELETED set.
- JAM_ChangeMsgHeader() decreases ActiveMsgs if JAM_MSG_DELETED is set and the
- message wasn't already deleted. JAM_DeleteMessage() now only decreases
- ActiveMsgs if the message wasn't already deleted.
- */
- /***********************************************************************
- **
- ** Message.C -- Message handling
- **
- ** Author: Bj”rn Stenberg ([email protected])
- **
- ***********************************************************************/
- #include <stdio.h>
- #include <errno.h>
- #include <stdlib.h>
- #include <string.h>
- #include "jam.h"
- #include "structrw.h"
- /***********************************************************************
- **
- ** JAM_ReadMsgHeader - Read message header
- **
- ***********************************************************************/
- int JAM_ReadMsgHeader( s_JamBase* Base_PS,
- uint32_t MsgNo_I,
- s_JamMsgHeader* Header_PS,
- s_JamSubPacket** SubfieldPack_PPS )
- {
- s_JamIndex Index_S;
- if ( !Base_PS || !Header_PS )
- return JAM_BAD_PARAM;
- /* find index record */
- if ( fseek( Base_PS->IdxFile_PS, MsgNo_I * sizeof( s_JamIndex ), SEEK_SET ) ) {
- Base_PS->Errno_I = errno;
- return JAM_IO_ERROR;
- }
- /* read index record */
- if ( 1 > freadjamindex(Base_PS->IdxFile_PS,&Index_S) ) {
- Base_PS->Errno_I = errno;
- return JAM_IO_ERROR;
- }
- /* message is not there */
- if(Index_S.HdrOffset == 0xffffffff && Index_S.UserCRC == 0xffffffff)
- {
- return JAM_NO_MESSAGE;
- }
- /* find header */
- if ( fseek( Base_PS->HdrFile_PS, Index_S.HdrOffset, SEEK_SET ) ) {
- Base_PS->Errno_I = errno;
- return JAM_IO_ERROR;
- }
- /* read header */
- if ( 1 > freadjammsgheader(Base_PS->HdrFile_PS,Header_PS) ) {
- Base_PS->Errno_I = errno;
- return JAM_IO_ERROR;
- }
- /* are Subfields requested? */
- if ( SubfieldPack_PPS && Header_PS->SubfieldLen ) {
- s_JamSubPacket* SubPacket_PS;
- s_JamSubfield Subfield_S;
- char* Buf_PC;
- char* Ptr_PC;
- char* Roof_PC;
- int BufSize_I = Header_PS->SubfieldLen;
- Buf_PC = (void*) malloc( BufSize_I );
- if ( !Buf_PC )
- return JAM_NO_MEMORY;
- /* read all subfields */
- if ( 1 > fread( Buf_PC, BufSize_I, 1, Base_PS->HdrFile_PS ) ) {
- Base_PS->Errno_I = errno;
- free (Buf_PC);
- return JAM_IO_ERROR;
- }
- SubPacket_PS = JAM_NewSubPacket();
- if ( !SubPacket_PS ) {
- free (Buf_PC);
- return JAM_NO_MEMORY;
- }
- Roof_PC = Buf_PC + BufSize_I;
- /* cut out the subfields */
- for ( Ptr_PC = Buf_PC;
- Ptr_PC < Roof_PC;
- Ptr_PC += Subfield_S.DatLen + SIZE_JAMSAVESUBFIELD ) {
- int Status_I;
- getjamsubfield(Ptr_PC,&Subfield_S);
- if((char *)Subfield_S.Buffer + Subfield_S.DatLen > Roof_PC) {
- JAM_DelSubPacket( SubPacket_PS );
- free (Buf_PC);
- return JAM_CORRUPT_MSG;
- }
- Status_I = JAM_PutSubfield( SubPacket_PS, &Subfield_S );
- if ( Status_I ) {
- JAM_DelSubPacket( SubPacket_PS );
- free (Buf_PC);
- return Status_I;
- }
- }
- free( Buf_PC );
- *SubfieldPack_PPS = SubPacket_PS;
- }
- else
- if ( SubfieldPack_PPS )
- /* fields requested but none found */
- /* return an empty packet */
- *SubfieldPack_PPS = JAM_NewSubPacket();
- return 0;
- }
- /***********************************************************************
- **
- ** JAM_ReadMsgText - Read message text
- **
- ***********************************************************************/
- int JAM_ReadMsgText( s_JamBase* Base_PS,
- uint32_t Offset_I,
- uint32_t Length_I,
- char* Buffer_PC )
- {
- if ( !Base_PS || !Buffer_PC )
- return JAM_BAD_PARAM;
- if ( !Length_I )
- return 0;
- if ( fseek( Base_PS->TxtFile_PS, Offset_I, SEEK_SET ) ) {
- Base_PS->Errno_I = errno;
- return JAM_IO_ERROR;
- }
- if ( 1 > fread( Buffer_PC, Length_I, 1, Base_PS->TxtFile_PS ) ) {
- Base_PS->Errno_I = errno;
- return JAM_IO_ERROR;
- }
- return 0;
- }
- /***********************************************************************
- **
- ** JAM_ChangeMsgHeader - Change a message header
- **
- ***********************************************************************/
- int JAM_ChangeMsgHeader( s_JamBase* Base_PS,
- uint32_t MsgNo_I,
- s_JamMsgHeader* Header_PS )
- {
- s_JamBaseHeader BaseHeader_S;
- s_JamMsgHeader OldHeader_S;
- s_JamIndex Index_S;
- int Status_I;
- if ( !Base_PS )
- return JAM_BAD_PARAM;
- if ( !Base_PS->Locked_I )
- return JAM_NOT_LOCKED;
- /* read message base header */
- Status_I = JAM_ReadMBHeader( Base_PS, &BaseHeader_S );
- if ( Status_I )
- return Status_I;
- /* find index record */
- if ( fseek( Base_PS->IdxFile_PS, MsgNo_I * sizeof( s_JamIndex ),
- SEEK_SET ) ) {
- Base_PS->Errno_I = errno;
- return JAM_IO_ERROR;
- }
- /* read index record */
- if ( 1 > freadjamindex(Base_PS->IdxFile_PS,&Index_S) ) {
- Base_PS->Errno_I = errno;
- return JAM_IO_ERROR;
- }
- /* find header */
- if ( fseek( Base_PS->HdrFile_PS, Index_S.HdrOffset, SEEK_SET ) ) {
- Base_PS->Errno_I = errno;
- return JAM_IO_ERROR;
- }
- /* read old message header */
- if ( 1 > freadjammsgheader( Base_PS->HdrFile_PS, &OldHeader_S ) ) {
- Base_PS->Errno_I = errno;
- return JAM_IO_ERROR;
- }
- /* find header */
- if ( fseek( Base_PS->HdrFile_PS, Index_S.HdrOffset, SEEK_SET ) ) {
- Base_PS->Errno_I = errno;
- return JAM_IO_ERROR;
- }
- /* write header */
- if ( 1 > fwritejammsgheader(Base_PS->HdrFile_PS,Header_PS) ) {
- Base_PS->Errno_I = errno;
- return JAM_IO_ERROR;
- }
- if( ( Header_PS->Attribute & JAM_MSG_DELETED ) && !(OldHeader_S.Attribute & JAM_MSG_DELETED) ) {
- /* message is deleted now but wasn't before */
- BaseHeader_S.ActiveMsgs--;
- }
- Status_I = JAM_WriteMBHeader( Base_PS, &BaseHeader_S );
- if ( Status_I )
- return Status_I;
- return 0;
- }
- /***********************************************************************
- **
- ** JAM_AddMessage - Add a message to a message base
- **
- ***********************************************************************/
- int JAM_AddMessage( s_JamBase* Base_PS,
- s_JamMsgHeader* Header_PS,
- s_JamSubPacket* SubPack_PS,
- char* Text_PC,
- uint32_t TextLen_I )
- {
- s_JamBaseHeader BaseHeader_S;
- s_JamIndex Index_S;
- long Offset_I;
- int Status_I;
- uint32_t TotLen_I;
- if ( !Base_PS )
- return JAM_BAD_PARAM;
- if ( !Base_PS->Locked_I )
- return JAM_NOT_LOCKED;
- /* read message base header */
- Status_I = JAM_ReadMBHeader( Base_PS, &BaseHeader_S );
- if ( Status_I )
- return Status_I;
- /*
- ** Add text if any
- */
- Header_PS->TxtOffset = 0;
- Header_PS->TxtLen = 0;
- if(Text_PC && TextLen_I!=0)
- {
- /* go to end of text file */
- if ( fseek( Base_PS->TxtFile_PS, 0, SEEK_END ) ) {
- Base_PS->Errno_I = errno;
- return JAM_IO_ERROR;
- }
- /* store text offset (for header) */
- Offset_I = ftell( Base_PS->TxtFile_PS );
- if ( Offset_I == -1 ) {
- Base_PS->Errno_I = errno;
- return JAM_IO_ERROR;
- }
- Header_PS->TxtOffset = Offset_I;
- Header_PS->TxtLen = TextLen_I;
- /* write text */
- if ( 1 > fwrite( Text_PC, TextLen_I, 1, Base_PS->TxtFile_PS ) ) {
- Base_PS->Errno_I = errno;
- return JAM_IO_ERROR;
- }
- }
- /*
- ** Add header
- */
- /* go to end of header file */
- if ( fseek( Base_PS->HdrFile_PS, 0, SEEK_END ) ) {
- Base_PS->Errno_I = errno;
- return JAM_IO_ERROR;
- }
- /* calculate the size of all Subfields */
- TotLen_I = 0;
- if ( SubPack_PS ) {
- s_JamSubfield* Subfield_PS;
- for ( Subfield_PS = JAM_GetSubfield( SubPack_PS ); Subfield_PS;
- Subfield_PS = JAM_GetSubfield( NULL ) )
- TotLen_I += sizeof( s_JamSaveSubfield ) + Subfield_PS->DatLen;
- }
- Header_PS->SubfieldLen = TotLen_I;
- /* go to end of index file */
- if ( fseek( Base_PS->IdxFile_PS, 0, SEEK_END ) ) {
- Base_PS->Errno_I = errno;
- return JAM_IO_ERROR;
- }
- /* find out new message number (for message header) */
- Offset_I = ftell( Base_PS->IdxFile_PS );
- if ( Offset_I == -1 ) {
- Base_PS->Errno_I = errno;
- return JAM_IO_ERROR;
- }
- /* update header */
- Header_PS->MsgNum = Offset_I / sizeof( s_JamIndex ) +
- BaseHeader_S.BaseMsgNum;
- memcpy( Header_PS->Signature, HEADERSIGNATURE, 4 );
- Header_PS->Revision = CURRENTREVLEV;
- /* go to end of header file */
- if ( fseek( Base_PS->HdrFile_PS, 0, SEEK_END ) ) {
- Base_PS->Errno_I = errno;
- return JAM_IO_ERROR;
- }
- /* find out new header offset (for index record) */
- Offset_I = ftell( Base_PS->HdrFile_PS );
- if ( Offset_I == -1 ) {
- Base_PS->Errno_I = errno;
- return JAM_IO_ERROR;
- }
- Index_S.HdrOffset = Offset_I;
- /* write new header */
- if ( 1 > fwritejammsgheader(Base_PS->HdrFile_PS,Header_PS) ) {
- Base_PS->Errno_I = errno;
- return JAM_IO_ERROR;
- }
- /* write Subfields */
- if ( SubPack_PS ) {
- s_JamSubfield* Subfield_PS;
- char User_AC[101];
- /* clear username */
- User_AC[0] = 0;
- for ( Subfield_PS = JAM_GetSubfield( SubPack_PS ); Subfield_PS;
- Subfield_PS = JAM_GetSubfield( NULL ) ) {
- /* first, save Subfield header */
- if ( 1 > fwritejamsavesubfield(Base_PS->HdrFile_PS,(s_JamSaveSubfield *)Subfield_PS) ) {
- Base_PS->Errno_I = errno;
- return JAM_IO_ERROR;
- }
- /* then, save Subfield data if any*/
- if(Subfield_PS->DatLen) {
- if ( 1 > fwrite( Subfield_PS->Buffer, Subfield_PS->DatLen,
- 1, Base_PS->HdrFile_PS ) ) {
- Base_PS->Errno_I = errno;
- return JAM_IO_ERROR;
- }
- }
- /* store username for index file */
- if ( Subfield_PS->LoID == JAMSFLD_RECVRNAME ) {
- memcpy( User_AC, Subfield_PS->Buffer, Subfield_PS->DatLen );
- User_AC[ Subfield_PS->DatLen ] = 0;
- }
- }
- /* update index record */
- if ( User_AC[0] )
- Index_S.UserCRC = JAM_Crc32( User_AC, strlen( User_AC ) );
- else
- Index_S.UserCRC = JAM_NO_CRC;
- }
- else
- /* update index record */
- Index_S.UserCRC = JAM_NO_CRC;
- /*
- ** Add index
- */
- /* write index record */
- if ( 1 > fwritejamindex(Base_PS->IdxFile_PS,&Index_S) ) {
- Base_PS->Errno_I = errno;
- return JAM_IO_ERROR;
- }
- if(!(Header_PS->Attribute & JAM_MSG_DELETED))
- BaseHeader_S.ActiveMsgs++; /* Only increase ActiveMsgs if JAM_MSG_DELETED not set */
- /* write message base header */
- Status_I = JAM_WriteMBHeader( Base_PS, &BaseHeader_S );
- if ( Status_I )
- return Status_I;
- return 0;
- }
- /***********************************************************************
- **
- ** JAM_AddEmptyMessage - Add a empty message entry to a message base
- **
- ***********************************************************************/
- int JAM_AddEmptyMessage( s_JamBase* Base_PS)
- {
- s_JamIndex Index_S;
- if ( !Base_PS )
- return JAM_BAD_PARAM;
- if ( !Base_PS->Locked_I )
- return JAM_NOT_LOCKED;
- /* go to end of index file */
- if ( fseek( Base_PS->IdxFile_PS, 0, SEEK_END ) ) {
- Base_PS->Errno_I = errno;
- return JAM_IO_ERROR;
- }
- /*
- ** Add index
- */
- Index_S.HdrOffset = 0xffffffff;
- Index_S.UserCRC = 0xffffffff;
- /* write index record */
- if ( 1 > fwritejamindex(Base_PS->IdxFile_PS,&Index_S) ) {
- Base_PS->Errno_I = errno;
- return JAM_IO_ERROR;
- }
- return 0;
- }
- /***********************************************************************
- **
- ** JAM_DeleteMessage - Delete message from messagebase
- **
- ***********************************************************************/
- int JAM_DeleteMessage( s_JamBase* Base_PS,
- uint32_t MsgNo_I )
- {
- s_JamBaseHeader BaseHeader_S;
- s_JamMsgHeader Header_S;
- s_JamIndex Index_S;
- int Status_I;
- uint32_t OldAttribute_I;
- if ( !Base_PS )
- return JAM_BAD_PARAM;
- if ( !Base_PS->Locked_I )
- return JAM_NOT_LOCKED;
- /* read message base header */
- Status_I = JAM_ReadMBHeader( Base_PS, &BaseHeader_S );
- if ( Status_I )
- return Status_I;
- /* find index record */
- if ( fseek( Base_PS->IdxFile_PS, MsgNo_I * sizeof( s_JamIndex ), SEEK_SET ) ) {
- Base_PS->Errno_I = errno;
- return JAM_IO_ERROR;
- }
- /* read index record */
- if ( 1 > freadjamindex( Base_PS->IdxFile_PS, &Index_S ) ) {
- Base_PS->Errno_I = errno;
- return JAM_IO_ERROR;
- }
- /* message is not there */
- if(Index_S.HdrOffset == 0xffffffff && Index_S.UserCRC == 0xffffffff)
- {
- return JAM_NO_MESSAGE;
- }
- /* find header */
- if ( fseek( Base_PS->HdrFile_PS, Index_S.HdrOffset, SEEK_SET ) ) {
- Base_PS->Errno_I = errno;
- return JAM_IO_ERROR;
- }
- /* read header */
- if ( 1 > freadjammsgheader( Base_PS->HdrFile_PS, &Header_S ) ) {
- Base_PS->Errno_I = errno;
- return JAM_IO_ERROR;
- }
- OldAttribute_I = Header_S.Attribute;
- Header_S.Attribute |= JAM_MSG_DELETED;
- /* find header */
- if ( fseek( Base_PS->HdrFile_PS, Index_S.HdrOffset, SEEK_SET ) ) {
- Base_PS->Errno_I = errno;
- return JAM_IO_ERROR;
- }
- /* write header */
- if ( 1 > fwritejammsgheader( Base_PS->HdrFile_PS, &Header_S ) ) {
- Base_PS->Errno_I = errno;
- return JAM_IO_ERROR;
- }
- /* find index record */
- if ( fseek( Base_PS->IdxFile_PS, MsgNo_I * sizeof( s_JamIndex ), SEEK_SET ) ) {
- Base_PS->Errno_I = errno;
- return JAM_IO_ERROR;
- }
- Index_S.HdrOffset = 0xffffffff;
- Index_S.UserCRC = 0xffffffff;
- /* write index record */
- if ( 1 > fwritejamindex(Base_PS->IdxFile_PS,&Index_S) ) {
- Base_PS->Errno_I = errno;
- return JAM_IO_ERROR;
- }
- if(!(OldAttribute_I & JAM_MSG_DELETED))
- BaseHeader_S.ActiveMsgs--; /* decrease ActiveMsgs if the message wasn't already deleted */
- /* write message base header */
- Status_I = JAM_WriteMBHeader( Base_PS, &BaseHeader_S );
- if ( Status_I )
- return Status_I;
- return 0;
- }
- /***********************************************************************
- **
- ** JAM_Errno - Report the latest C library error code
- **
- ***********************************************************************/
- int JAM_Errno( s_JamBase* Base_PS )
- {
- return Base_PS->Errno_I;
- }
- /***********************************************************************
- **
- ** JAM_ClearMsgHeader - Clear a message header
- **
- ***********************************************************************/
- int JAM_ClearMsgHeader( s_JamMsgHeader* Header_PS )
- {
- if (!Header_PS)
- return JAM_BAD_PARAM;
- memset( Header_PS, 0, sizeof( s_JamMsgHeader ) );
- memcpy( Header_PS->Signature, HEADERSIGNATURE, 4 );
- Header_PS->Revision = CURRENTREVLEV;
- Header_PS->MsgIdCRC = JAM_NO_CRC;
- Header_PS->ReplyCRC = JAM_NO_CRC;
- Header_PS->PasswordCRC = JAM_NO_CRC;
- return 0;
- }
|