2000-02-25 10:15:17 +00:00
|
|
|
// This may look like C code, but it is really -*- C++ -*-
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------
|
|
|
|
// The Goldware Library
|
|
|
|
// Copyright (C) 1990-1999 Odinn Sorensen
|
|
|
|
// ------------------------------------------------------------------
|
|
|
|
// This library is free software; you can redistribute it and/or
|
|
|
|
// modify it under the terms of the GNU Library General Public
|
|
|
|
// License as published by the Free Software Foundation; either
|
|
|
|
// version 2 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
|
|
|
|
// Library General Public License for more details.
|
|
|
|
//
|
|
|
|
// You should have received a copy of the GNU Library General Public
|
|
|
|
// License along with this program; if not, write to the Free
|
|
|
|
// Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
|
|
|
// MA 02111-1307, USA
|
|
|
|
// ------------------------------------------------------------------
|
|
|
|
// $Id$
|
|
|
|
// ------------------------------------------------------------------
|
|
|
|
// AdeptXBBS messagebase engine.
|
|
|
|
// ------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------
|
|
|
|
|
|
|
|
#include <gdbgerr.h>
|
|
|
|
#include <gmemdbg.h>
|
|
|
|
#include <gdbgtrk.h>
|
|
|
|
#include <gstrall.h>
|
|
|
|
#include <gcrcall.h>
|
|
|
|
#include <gutlmisc.h>
|
|
|
|
|
|
|
|
#include <gmoxbbs.h>
|
|
|
|
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------
|
|
|
|
|
|
|
|
void XbbsArea::lock() {
|
|
|
|
|
|
|
|
// Not applicable in AdeptXBBS
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------
|
|
|
|
|
|
|
|
void XbbsArea::unlock() {
|
|
|
|
|
|
|
|
// Not applicable in AdeptXBBS
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------
|
|
|
|
|
2005-10-07 12:41:11 +00:00
|
|
|
void XbbsArea::lock_file(int handle, int32_t position, int32_t length) {
|
2000-02-25 10:15:17 +00:00
|
|
|
|
|
|
|
GFTRK("XbbsLockFile");
|
|
|
|
|
|
|
|
long tries = 0;
|
|
|
|
while(::lock(handle, position, length) == -1) {
|
2002-05-12 13:07:37 +00:00
|
|
|
if(PopupLocked(++tries, true, real_path()) == false) {
|
2000-02-25 10:15:17 +00:00
|
|
|
WideLog->ErrLock();
|
|
|
|
raw_close();
|
|
|
|
Path file;
|
2002-05-12 13:07:37 +00:00
|
|
|
strcpy(file, real_path());
|
2000-02-25 10:15:17 +00:00
|
|
|
if(handle == data->fhdata)
|
|
|
|
strcat(file, ".Data");
|
|
|
|
else if(handle == data->fhtext)
|
|
|
|
strcat(file, ".Text");
|
|
|
|
else if(handle == data->fhindex)
|
|
|
|
strcat(file, ".Index");
|
|
|
|
else if(handle == wide->fhpmi)
|
|
|
|
sprintf(file, "%sPersonal_Mail\\%s", wide->path, WideUsername[0]);
|
|
|
|
WideLog->printf("! An AdeptXBBS msgbase file could not be locked.");
|
|
|
|
WideLog->printf(": %s.", file);
|
|
|
|
WideLog->ErrOSInfo();
|
|
|
|
LockErrorExit();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(tries)
|
|
|
|
PopupLocked(0, 0, NULL);
|
|
|
|
|
|
|
|
GFTRK(NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------
|
|
|
|
|
2005-10-07 12:41:11 +00:00
|
|
|
void XbbsArea::unlock_file(int handle, int32_t position, int32_t length) {
|
2000-02-25 10:15:17 +00:00
|
|
|
|
|
|
|
GFTRK("XbbsUnlockFile");
|
|
|
|
|
|
|
|
::unlock(handle, position, length);
|
|
|
|
|
|
|
|
GFTRK(NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------
|
|
|
|
|
2005-10-21 19:48:21 +00:00
|
|
|
uint16_t XbbsCheckSum(char* str) {
|
2000-02-25 10:15:17 +00:00
|
|
|
|
2005-10-21 19:48:21 +00:00
|
|
|
uint16_t checksum = 0;
|
2000-02-25 10:15:17 +00:00
|
|
|
|
|
|
|
while(*str) {
|
2005-10-21 19:48:21 +00:00
|
|
|
checksum ^= (uint16_t)toupper(*str++);
|
2000-02-25 10:15:17 +00:00
|
|
|
if(checksum & 1)
|
2005-10-21 19:48:21 +00:00
|
|
|
checksum = (uint16_t)((checksum >> 1) ^ 0xA000);
|
2000-02-25 10:15:17 +00:00
|
|
|
else
|
|
|
|
checksum >>= 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return checksum;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------
|
|
|
|
|
|
|
|
void XbbsArea::save_message(int __mode, gmsg* __msg, XbbsHdr& __hdr) {
|
|
|
|
|
|
|
|
// Reset header
|
|
|
|
memset(&__hdr, 0, sizeof(XbbsHdr));
|
|
|
|
|
|
|
|
if(__mode & GMSG_NEW) {
|
|
|
|
data->idx_size++;
|
|
|
|
__msg->msgno = data->idx_size;
|
|
|
|
Msgn->Append(__msg->msgno);
|
|
|
|
data->idx = (XbbsIdx*)throw_realloc(data->idx, data->idx_size*sizeof(XbbsIdx));
|
|
|
|
}
|
|
|
|
|
|
|
|
strxcpy(__hdr.from, __msg->by, sizeof(__hdr.from));
|
|
|
|
strxcpy(__hdr.to, __msg->to, sizeof(__hdr.to));
|
|
|
|
strxcpy(__hdr.subj, __msg->re, sizeof(__hdr.subj));
|
|
|
|
|
2005-10-17 19:51:33 +00:00
|
|
|
struct tm* _tm = ggmtime(&__msg->written);
|
2000-02-25 10:15:17 +00:00
|
|
|
sprintf(__hdr.date, "%02d %3s %02d %02d:%02d:%02d",
|
|
|
|
_tm->tm_mday, gmonths[_tm->tm_mon+1], _tm->tm_year % 100,
|
|
|
|
_tm->tm_hour, _tm->tm_min, _tm->tm_sec
|
|
|
|
);
|
|
|
|
if(__msg->arrived)
|
2005-10-17 19:51:33 +00:00
|
|
|
_tm = ggmtime(&__msg->arrived);
|
2000-02-25 10:15:17 +00:00
|
|
|
__hdr.indate[0] = (byte)(_tm->tm_year - 89);
|
|
|
|
__hdr.indate[1] = (byte)(_tm->tm_mon + 1);
|
|
|
|
__hdr.indate[2] = (byte)(_tm->tm_mday);
|
|
|
|
__hdr.indate[3] = 0;
|
|
|
|
|
|
|
|
__hdr.msgnum = __msg->msgno;
|
|
|
|
__hdr.timesread = __msg->timesread;
|
|
|
|
__hdr.timerecv = __msg->received;
|
|
|
|
__hdr.origaddr = __msg->oorig;
|
|
|
|
__hdr.destaddr = __msg->odest;
|
2005-10-21 19:48:21 +00:00
|
|
|
__hdr.cost = (uint16_t)__msg->cost;
|
2000-02-25 10:15:17 +00:00
|
|
|
|
|
|
|
// Transfer attributes
|
2005-10-21 19:48:21 +00:00
|
|
|
__hdr.fflags |= (uint16_t)(__msg->attr.pvt() ? FFLAGS_MSGPRIVATE : 0);
|
|
|
|
__hdr.fflags |= (uint16_t)(__msg->attr.cra() ? FFLAGS_MSGCRASH : 0);
|
|
|
|
__hdr.fflags |= (uint16_t)(__msg->attr.rcv() ? FFLAGS_MSGREAD : 0);
|
|
|
|
__hdr.fflags |= (uint16_t)(__msg->attr.snt() ? FFLAGS_MSGSENT : 0);
|
|
|
|
__hdr.fflags |= (uint16_t)(__msg->attr.att() ? FFLAGS_MSGFILE : 0);
|
|
|
|
__hdr.fflags |= (uint16_t)(__msg->attr.trs() ? FFLAGS_MSGFWD : 0);
|
|
|
|
__hdr.fflags |= (uint16_t)(__msg->attr.orp() ? FFLAGS_MSGORPHAN : 0);
|
|
|
|
__hdr.fflags |= (uint16_t)(__msg->attr.k_s() ? FFLAGS_MSGKILL : 0);
|
|
|
|
__hdr.fflags |= (uint16_t)(__msg->attr.loc() ? FFLAGS_MSGLOCAL : 0);
|
|
|
|
__hdr.fflags |= (uint16_t)(__msg->attr.rsv() ? FFLAGS_MSGXX2 : 0);
|
|
|
|
__hdr.fflags |= (uint16_t)(__msg->attr.frq() ? FFLAGS_MSGFRQ : 0);
|
|
|
|
__hdr.fflags |= (uint16_t)(__msg->attr.rrq() ? FFLAGS_MSGRRQ : 0);
|
|
|
|
__hdr.fflags |= (uint16_t)(__msg->attr.rrc() ? FFLAGS_MSGCPT : 0);
|
|
|
|
__hdr.fflags |= (uint16_t)(__msg->attr.arq() ? FFLAGS_MSGARQ : 0);
|
|
|
|
__hdr.fflags |= (uint16_t)(__msg->attr.urq() ? FFLAGS_MSGURQ : 0);
|
|
|
|
|
|
|
|
__hdr.xflags |= (uint16_t)(__msg->attr.del() ? XFLAGS_MSGDELETED : 0);
|
|
|
|
__hdr.xflags |= (uint16_t)(__msg->attr.ano() ? XFLAGS_MSGANON : 0);
|
|
|
|
__hdr.xflags |= (uint16_t)(__msg->attr.fsc() ? XFLAGS_MSGSCANNED : 0);
|
|
|
|
__hdr.xflags |= (uint16_t)(__msg->attr.lok() ? XFLAGS_MSGKEEP : 0);
|
|
|
|
__hdr.xflags |= (uint16_t)(__msg->attr.trt() ? XFLAGS_MSGTREATED : 0);
|
|
|
|
__hdr.xflags |= (uint16_t)(__msg->attr.lzs() ? XFLAGS_MSGPACKED : 0);
|
|
|
|
__hdr.xflags |= (uint16_t)(__msg->attr.gsc() ? XFLAGS_MSGGSCAN : 0);
|
|
|
|
__hdr.xflags |= (uint16_t)(__msg->attr.rsc() ? XFLAGS_MSGRSCAN : 0);
|
|
|
|
__hdr.xflags |= (uint16_t)(__msg->attr.arc() ? XFLAGS_MSGARCHIVED : 0);
|
|
|
|
__hdr.xflags |= (uint16_t)(__msg->attr.tag() ? XFLAGS_MSGTAGGED : 0);
|
2000-02-25 10:15:17 +00:00
|
|
|
|
2001-04-15 19:24:44 +00:00
|
|
|
if(not (__mode & GMSG_UPDATE)) {
|
2000-02-25 10:15:17 +00:00
|
|
|
if(__msg->attr.uns()) {
|
|
|
|
__hdr.xflags &= ~(XFLAGS_MSGSCANNED|XFLAGS_MSGGSCAN|XFLAGS_MSGRSCAN);
|
|
|
|
if(isnet())
|
|
|
|
__hdr.xflags |= XFLAGS_MSGNET;
|
|
|
|
else if(isecho())
|
|
|
|
__hdr.xflags |= XFLAGS_MSGECHO;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if(isnet()) {
|
|
|
|
__hdr.fflags |= FFLAGS_MSGSENT;
|
|
|
|
__hdr.xflags |= XFLAGS_MSGNET | XFLAGS_MSGSCANNED;
|
|
|
|
}
|
|
|
|
else if(isecho()) {
|
|
|
|
__hdr.fflags |= FFLAGS_MSGSENT;
|
|
|
|
__hdr.xflags |= XFLAGS_MSGECHO | XFLAGS_MSGSCANNED;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
__hdr.iflags = __msg->adeptxbbs.iflags;
|
|
|
|
__hdr.oflags = __msg->adeptxbbs.oflags;
|
|
|
|
|
|
|
|
__hdr.start = __msg->txtstart;
|
|
|
|
__hdr.length = __msg->txtlength;
|
|
|
|
|
|
|
|
if(__mode & GMSG_TXT) {
|
|
|
|
|
|
|
|
// Write the message text
|
|
|
|
uint _size = strlen(__msg->txt) + 1;
|
2001-04-15 19:24:44 +00:00
|
|
|
if((__mode & GMSG_NEW) or (_size > __hdr.length))
|
2000-02-25 10:15:17 +00:00
|
|
|
__hdr.start = filelength(data->fhtext);
|
|
|
|
lseekset(data->fhtext, __hdr.start);
|
|
|
|
lock_file(data->fhtext, __hdr.start, 640L*1024L);
|
|
|
|
write(data->fhtext, __msg->txt, _size);
|
|
|
|
unlock_file(data->fhtext, __hdr.start, 640L*1024L);
|
|
|
|
__hdr.length = _size;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Write header record
|
2005-10-07 12:41:11 +00:00
|
|
|
int32_t position = (__msg->msgno-1L)*sizeof(XbbsHdr);
|
2000-02-25 10:15:17 +00:00
|
|
|
lseekset(data->fhdata, position);
|
|
|
|
lock_file(data->fhdata, position, sizeof(XbbsHdr));
|
|
|
|
write(data->fhdata, &__hdr, sizeof(XbbsHdr));
|
|
|
|
unlock_file(data->fhdata, position, sizeof(XbbsHdr));
|
|
|
|
|
|
|
|
// Build and write index record unless we are just updating the header
|
|
|
|
if(__mode & GMSG_TXT) {
|
|
|
|
XbbsIdx idx;
|
|
|
|
char buf[201];
|
|
|
|
idx.to = XbbsCheckSum(__hdr.to);
|
|
|
|
idx.from = XbbsCheckSum(__hdr.from);
|
|
|
|
idx.subj = XbbsCheckSum(__hdr.subj);
|
|
|
|
idx.msgidcrc = idx.msgidserialno = 0;
|
|
|
|
idx.replycrc = idx.replyserialno = 0;
|
|
|
|
if(*__msg->msgids) {
|
|
|
|
strcpy(buf, __msg->msgids);
|
|
|
|
char* ptr = strrchr(buf, ' ');
|
|
|
|
if(ptr) {
|
|
|
|
*ptr++ = NUL;
|
|
|
|
idx.msgidcrc = strCrc32(buf, true, CRC32_MASK_CCITT);
|
|
|
|
idx.msgidserialno = atoulx(ptr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(*__msg->replys) {
|
|
|
|
strcpy(buf, __msg->replys);
|
|
|
|
char* ptr = strrchr(buf, ' ');
|
|
|
|
if(ptr) {
|
|
|
|
*ptr++ = NUL;
|
|
|
|
idx.replycrc = strCrc32(buf, true, CRC32_MASK_CCITT);
|
|
|
|
idx.replyserialno = atoulx(ptr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
memcpy(data->idx+__msg->msgno-1, &idx, sizeof(XbbsIdx));
|
2005-10-07 12:41:11 +00:00
|
|
|
position = (__msg->msgno-1L)*sizeof(XbbsIdx);
|
2000-02-25 10:15:17 +00:00
|
|
|
lseekset(data->fhindex, position);
|
|
|
|
lock_file(data->fhindex, position, sizeof(XbbsIdx));
|
|
|
|
write(data->fhindex, &idx, sizeof(XbbsIdx));
|
|
|
|
unlock_file(data->fhindex, position, sizeof(XbbsIdx));
|
|
|
|
}
|
|
|
|
|
2001-04-15 19:24:44 +00:00
|
|
|
if(not (__mode & GMSG_DELETE)) {
|
2000-02-25 10:15:17 +00:00
|
|
|
// Add/update personal mail record
|
|
|
|
int _addpm = true;
|
|
|
|
// Remove it if the msg is being received
|
2001-04-15 19:24:44 +00:00
|
|
|
if((__mode & GMSG_UPDATE) and __msg->attr.rcv())
|
2000-02-25 10:15:17 +00:00
|
|
|
_addpm = false;
|
|
|
|
// Don't touch it if the msg was already received
|
2001-04-15 19:24:44 +00:00
|
|
|
if(not (_addpm and __msg->attr.rcv())) {
|
2000-02-25 10:15:17 +00:00
|
|
|
// Only do it if the person is on this BBS
|
|
|
|
if(wide->user->find(__msg->to))
|
|
|
|
update_personal_mail(__msg, __hdr, _addpm);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
GFTRK(NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------
|
|
|
|
|
|
|
|
void XbbsArea::save_hdr(int __mode, gmsg* __msg) {
|
|
|
|
|
|
|
|
GFTRK("XbbsSaveHdr");
|
|
|
|
|
|
|
|
XbbsHdr _hdr;
|
|
|
|
save_message(__mode|GMSG_HDR, __msg, _hdr);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------
|
|
|
|
|
|
|
|
void XbbsArea::save_msg(int __mode, gmsg* __msg) {
|
|
|
|
|
|
|
|
GFTRK("XbbsSaveMsg");
|
|
|
|
|
|
|
|
XbbsHdr _hdr;
|
|
|
|
save_message(__mode|GMSG_HDRTXT, __msg, _hdr);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------
|
|
|
|
|
|
|
|
void XbbsArea::del_msg(gmsg* __msg) {
|
|
|
|
|
|
|
|
GFTRK("XbbsDelMsg");
|
|
|
|
|
|
|
|
XbbsHdr _hdr;
|
|
|
|
save_message(GMSG_HDR | GMSG_DELETE, __msg, _hdr);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------
|
|
|
|
|
|
|
|
void XbbsArea::new_msgno(gmsg* __msg) {
|
|
|
|
|
|
|
|
GFTRK("XbbsNewMsgno");
|
|
|
|
|
|
|
|
__msg->msgno = data->idx_size + 1;
|
|
|
|
|
|
|
|
GFTRK(NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------
|
|
|
|
|
|
|
|
void XbbsArea::update_personal_mail(gmsg* __msg, XbbsHdr& __hdr, int __addpm) {
|
|
|
|
|
|
|
|
XbbsPmi _pmi;
|
|
|
|
_pmi.areanumber = board();
|
|
|
|
_pmi.msgnumber = __msg->msgno;
|
|
|
|
strxcpy(_pmi.from, __msg->by, sizeof(_pmi.from));
|
|
|
|
strxcpy(_pmi.subject, __msg->re, sizeof(_pmi.subject));
|
|
|
|
strxcpy(_pmi.date, __hdr.date, sizeof(_pmi.date));
|
|
|
|
|
|
|
|
int _pmino = 0;
|
|
|
|
XbbsPmi* _pmiptr = NULL;
|
|
|
|
|
|
|
|
gfile fp;
|
|
|
|
Path _pmifile;
|
|
|
|
sprintf(_pmifile, "%sPersonal_Mail\\%s", wide->path, __hdr.to);
|
|
|
|
int fh = test_open(_pmifile, SH_DENYWR);
|
|
|
|
|
|
|
|
int _pmirecs = (int)(filelength(fh) / sizeof(XbbsPmi));
|
|
|
|
XbbsPmi* _pmilist = (XbbsPmi*)throw_calloc((_pmirecs+1), sizeof(XbbsPmi));
|
|
|
|
::read(fh, _pmilist, sizeof(XbbsPmi)*_pmirecs);
|
|
|
|
|
|
|
|
if(_pmilist) {
|
|
|
|
_pmiptr = _pmilist;
|
|
|
|
for(_pmino=0; _pmino<_pmirecs; _pmino++, _pmiptr++) {
|
|
|
|
if(_pmiptr->areanumber == _pmi.areanumber)
|
|
|
|
if(_pmiptr->msgnumber == _pmi.msgnumber)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if(_pmino == _pmirecs)
|
|
|
|
_pmiptr = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(__addpm) {
|
|
|
|
if(!_pmiptr) {
|
|
|
|
_pmirecs++;
|
|
|
|
_pmilist = (XbbsPmi*)throw_realloc(_pmilist, _pmirecs*sizeof(XbbsPmi));
|
|
|
|
_pmiptr = _pmilist + _pmirecs - 1;
|
|
|
|
}
|
|
|
|
memcpy(_pmiptr, &_pmi, sizeof(XbbsPmi));
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if(_pmiptr) {
|
|
|
|
memmove(_pmiptr, _pmiptr+1, (_pmirecs-_pmino-1)*sizeof(XbbsPmi));
|
|
|
|
_pmirecs--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(_pmirecs) {
|
|
|
|
lseekset(fh, 0);
|
|
|
|
::write(fh, _pmilist, sizeof(XbbsPmi)*_pmirecs);
|
2001-04-15 19:24:44 +00:00
|
|
|
if(_pmiptr and not __addpm)
|
2000-02-25 10:15:17 +00:00
|
|
|
chsize(fh, sizeof(XbbsPmi)*_pmirecs);
|
|
|
|
::close(fh);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
::close(fh);
|
|
|
|
remove(_pmifile);
|
|
|
|
}
|
|
|
|
|
|
|
|
throw_free(_pmilist);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------
|
|
|
|
|
|
|
|
void XbbsArea::update_timesread(gmsg* msg) {
|
|
|
|
|
|
|
|
GFTRK("XbbsArea::update_timesread");
|
|
|
|
|
|
|
|
XbbsHdr hdr;
|
|
|
|
|
2005-10-07 12:41:11 +00:00
|
|
|
int32_t position = (Msgn->ToReln(msg->msgno)-1)*sizeof(XbbsHdr);
|
2000-02-25 10:15:17 +00:00
|
|
|
|
|
|
|
::lseekset(data->fhdata, position);
|
|
|
|
::read(data->fhdata, &hdr, sizeof(XbbsHdr));
|
|
|
|
|
|
|
|
hdr.timesread = (word)msg->timesread;
|
|
|
|
|
|
|
|
::lseekset(data->fhdata, position);
|
|
|
|
lock_file(data->fhdata, position, sizeof(XbbsHdr));
|
|
|
|
::write(data->fhdata, &hdr, sizeof(XbbsHdr));
|
|
|
|
unlock_file(data->fhdata, position, sizeof(XbbsHdr));
|
|
|
|
|
|
|
|
GFTRK(NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------
|
|
|
|
|