Annotation of sbbs/sbbs3/smblib.c, revision 1.1

1.1     ! root        1: /* smblib.c */
        !             2: 
        !             3: /* Synchronet message base (SMB) library routines */
        !             4: 
        !             5: /* $Id: smblib.c,v 1.8 2000/11/04 12:03:51 rswindell Exp $ */
        !             6: 
        !             7: /****************************************************************************
        !             8:  * @format.tab-size 4          (Plain Text/Source Code File Header)                    *
        !             9:  * @format.use-tabs true       (see http://www.synchro.net/ptsc_hdr.html)              *
        !            10:  *                                                                                                                                                     *
        !            11:  * Copyright 2000 Rob Swindell - http://www.synchro.net/copyright.html         *
        !            12:  *                                                                                                                                                     *
        !            13:  * This library is free software; you can redistribute it and/or                       *
        !            14:  * modify it under the terms of the GNU Lesser General Public License          *
        !            15:  * as published by the Free Software Foundation; either version 2                      *
        !            16:  * of the License, or (at your option) any later version.                                      *
        !            17:  * See the GNU Lesser General Public License for more details: lgpl.txt or     *
        !            18:  * http://www.fsf.org/copyleft/lesser.html                                                                     *
        !            19:  *                                                                                                                                                     *
        !            20:  * Anonymous FTP access to the most recent released source is available at     *
        !            21:  * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net     *
        !            22:  *                                                                                                                                                     *
        !            23:  * Anonymous CVS access to the development source and modification history     *
        !            24:  * is available at cvs.synchro.net:/cvsroot/sbbs, example:                                     *
        !            25:  * cvs -d :pserver:[email protected]:/cvsroot/sbbs login                       *
        !            26:  *     (just hit return, no password is necessary)                                                     *
        !            27:  * cvs -d :pserver:[email protected]:/cvsroot/sbbs checkout src                *
        !            28:  *                                                                                                                                                     *
        !            29:  * For Synchronet coding style and modification guidelines, see                                *
        !            30:  * http://www.synchro.net/source.html                                                                          *
        !            31:  *                                                                                                                                                     *
        !            32:  * You are encouraged to submit any modifications (preferably in Unix diff     *
        !            33:  * format) via e-mail to [email protected]                                                                      *
        !            34:  *                                                                                                                                                     *
        !            35:  * Note: If this box doesn't appear square, then you need to fix your tabs.    *
        !            36:  ****************************************************************************/
        !            37: 
        !            38: #if defined __WATCOMC__ || defined __TURBOC__
        !            39:        #include <mem.h>
        !            40: #else
        !            41:        #include <memory.h>
        !            42: #endif
        !            43: 
        !            44: #ifdef __WATCOMC__
        !            45:        #include <dos.h>
        !            46: #elif defined __TURBOC__
        !            47:        #include <dir.h>
        !            48: #endif
        !            49: 
        !            50: /* ANSI C Library headers */
        !            51: #include <malloc.h>
        !            52: #include <time.h>
        !            53: #include <errno.h>
        !            54: #include <fcntl.h>
        !            55: #include <stdio.h>
        !            56: #include <stdlib.h>
        !            57: #include <string.h>
        !            58: #include <sys/stat.h>
        !            59: #include <sys/types.h>
        !            60: 
        !            61: /* SMB-specific headers */
        !            62: #include "smblib.h"
        !            63: #include "smbwrap.h"
        !            64: 
        !            65: /* Use smb_ver() and smb_lib_ver() to obtain these values */
        !            66: #define SMBLIB_VERSION         "2.13"      /* SMB library version */
        !            67: #define SMB_VERSION            0x0121          /* SMB format version */
        !            68:                                                                                /* High byte major, low byte minor */
        !            69: 
        !            70: int SMBCALL smb_ver(void)
        !            71: {
        !            72:        return(SMB_VERSION);
        !            73: }
        !            74: 
        !            75: char* SMBCALL smb_lib_ver(void)
        !            76: {
        !            77:        return(SMBLIB_VERSION);
        !            78: }
        !            79: 
        !            80: /****************************************************************************/
        !            81: /* Open a message base of name 'smb->file'                                  */
        !            82: /* Opens files for READing messages or updating message indices only        */
        !            83: /****************************************************************************/
        !            84: int SMBCALL smb_open(smb_t* smb)
        !            85: {
        !            86:     int file;
        !            87:     char str[128];
        !            88:        smbhdr_t hdr;
        !            89: 
        !            90:        if(!smb->retry_time)
        !            91:                smb->retry_time=10;
        !            92:        smb->shd_fp=smb->sdt_fp=smb->sid_fp=NULL;
        !            93:        sprintf(str,"%s.shd",smb->file);
        !            94:        if((file=sopen(str,O_RDWR|O_CREAT|O_BINARY,SH_DENYNO))==-1
        !            95:                || (smb->shd_fp=fdopen(file,"r+b"))==NULL) {
        !            96:                sprintf(smb->last_error,"%d opening %s",errno,str);
        !            97:                if(file!=-1)
        !            98:                        close(file);
        !            99:                return(2)        !           100:        }
        !           101: 
        !           102:        if(filelength(file)>=sizeof(smbhdr_t)) {
        !           103:                setvbuf(smb->shd_fp,smb->shd_buf,_IONBF,SHD_BLOCK_LEN);
        !           104:                if(smb_locksmbhdr(smb)!=0) {
        !           105:                        smb_close(smb);
        !           106:                        /* smb_lockmsghdr set last_error */
        !           107:                        return(-1); 
        !           108:                }
        !           109:                memset(&hdr,0,sizeof(smbhdr_t));
        !           110:                if(fread(&hdr,sizeof(smbhdr_t),1,smb->shd_fp)!=1) {
        !           111:                        sprintf(smb->last_error,"reading header");
        !           112:                        smb_close(smb);
        !           113:                        return(-10);
        !           114:                }
        !           115:                if(memcmp(hdr.id,"SMB\x1a",4)) {
        !           116:                        sprintf(smb->last_error,"corrupt header id: %.4s",hdr.id);
        !           117:                        smb_close(smb);
        !           118:                        return(-2); 
        !           119:                }
        !           120:                if(hdr.version<0x110) {         /* Compatibility check */
        !           121:                        sprintf(smb->last_error,"insufficient header version: %X",hdr.version);
        !           122:                        smb_close(smb);
        !           123:                        return(-3); 
        !           124:                }
        !           125:                if(fread(&(smb->status),1,sizeof(smbstatus_t),smb->shd_fp)
        !           126:                        !=sizeof(smbstatus_t)) {
        !           127:                        sprintf(smb->last_error,"failed to read status");
        !           128:                        smb_close(smb);
        !           129:                        return(-4); 
        !           130:                }
        !           131:                smb_unlocksmbhdr(smb);
        !           132:                rewind(smb->shd_fp); 
        !           133:        }
        !           134: 
        !           135:        setvbuf(smb->shd_fp,smb->shd_buf,_IOFBF,SHD_BLOCK_LEN);
        !           136: 
        !           137:        sprintf(str,"%s.sdt",smb->file);
        !           138:        if((file=sopen(str,O_RDWR|O_CREAT|O_BINARY,SH_DENYNO))==-1
        !           139:                || (smb->sdt_fp=fdopen(file,"r+b"))==NULL) {
        !           140:                sprintf(smb->last_error,"%d opening %s",errno,str);
        !           141:                if(file!=-1)
        !           142:                        close(file);
        !           143:                smb_close(smb);
        !           144:                return(1)        !           145:        }
        !           146:        setvbuf(smb->sdt_fp,NULL,_IOFBF,2*1024);
        !           147: 
        !           148:        sprintf(str,"%s.sid",smb->file);
        !           149:        if((file=sopen(str,O_RDWR|O_CREAT|O_BINARY,SH_DENYNO))==-1
        !           150:                || (smb->sid_fp=fdopen(file,"r+b"))==NULL) {
        !           151:                sprintf(smb->last_error,"%d opening %s",errno,str);
        !           152:                if(file!=-1)
        !           153:                        close(file);
        !           154:                smb_close(smb);
        !           155:                return(3)        !           156:        }
        !           157:        setvbuf(smb->sid_fp,NULL,_IOFBF,2*1024);
        !           158: 
        !           159:        return(0);
        !           160: }
        !           161: 
        !           162: /****************************************************************************/
        !           163: /* Closes the currently open message base                                                                      */
        !           164: /****************************************************************************/
        !           165: void SMBCALL smb_close(smb_t* smb)
        !           166: {
        !           167:        if(smb->shd_fp!=NULL) {
        !           168:                smb_unlocksmbhdr(smb);             /* In case it's been locked */
        !           169:                fclose(smb->shd_fp); 
        !           170:        }
        !           171:        if(smb->sid_fp!=NULL)
        !           172:                fclose(smb->sid_fp);
        !           173:        if(smb->sdt_fp!=NULL)
        !           174:                fclose(smb->sdt_fp);
        !           175:        smb->sid_fp=smb->shd_fp=smb->sdt_fp=NULL;
        !           176: }
        !           177: 
        !           178: /****************************************************************************/
        !           179: /* Opens the data block allocation table message base 'smb->file'           */
        !           180: /* Retrys for retry_time number of seconds                                                                     */
        !           181: /* Return 0 on success, non-zero otherwise                                                                     */
        !           182: /****************************************************************************/
        !           183: int SMBCALL smb_open_da(smb_t* smb)
        !           184: {
        !           185:        int     file;
        !           186:        char    str[128];
        !           187:        ulong   start=0;
        !           188: 
        !           189:        sprintf(str,"%s.sda",smb->file);
        !           190:        while(1) {
        !           191:                if((file=sopen(str,O_RDWR|O_CREAT|O_BINARY,SH_DENYRW))!=-1)
        !           192:                        break;
        !           193:                if(errno!=EACCES) {
        !           194:                        sprintf(smb->last_error,"%d opening %s",errno,str);
        !           195:                        return(-1);
        !           196:                }
        !           197:                if(!start)
        !           198:                        start=time(NULL);
        !           199:                else
        !           200:                        if(time(NULL)-start>=smb->retry_time) {
        !           201:                                sprintf(smb->last_error,"timeout opening %s",str);
        !           202:                                return(-2); 
        !           203:                        }
        !           204:        }
        !           205:        if((smb->sda_fp=fdopen(file,"r+b"))==NULL) {
        !           206:                sprintf(smb->last_error,"%d fdopening %s",errno,str);
        !           207:                close(file);
        !           208:                return(-3); 
        !           209:        }
        !           210:        setvbuf(smb->sda_fp,NULL,_IOFBF,2*1024);
        !           211:        return(0);
        !           212: }
        !           213: 
        !           214: void SMBCALL smb_close_da(smb_t* smb)
        !           215: {
        !           216:        if(smb->sda_fp!=NULL)
        !           217:                fclose(smb->sda_fp);
        !           218:        smb->sda_fp=NULL;
        !           219: }
        !           220: 
        !           221: /****************************************************************************/
        !           222: /* Opens the header block allocation table for message base 'smb.file'      */
        !           223: /* Retrys for smb.retry_time number of seconds                                                         */
        !           224: /* Return 0 on success, non-zero otherwise                                                                     */
        !           225: /****************************************************************************/
        !           226: int SMBCALL smb_open_ha(smb_t* smb)
        !           227: {
        !           228:        int     file;
        !           229:        char    str[128];
        !           230:        ulong   start=0;
        !           231: 
        !           232:        sprintf(str,"%s.sha",smb->file);
        !           233:        while(1) {
        !           234:                if((file=sopen(str,O_RDWR|O_CREAT|O_BINARY,SH_DENYRW))!=-1)
        !           235:                        break;
        !           236:                if(errno!=EACCES) {
        !           237:                        sprintf(smb->last_error,"%d opening %s",errno,str);
        !           238:                        return(-1);
        !           239:                }
        !           240:                if(!start)
        !           241:                        start=time(NULL);
        !           242:                else
        !           243:                        if(time(NULL)-start>=smb->retry_time) {
        !           244:                                sprintf(smb->last_error,"timeout opening %s",str);
        !           245:                                return(-2); 
        !           246:                        }
        !           247:        }
        !           248:        if((smb->sha_fp=fdopen(file,"r+b"))==NULL) {
        !           249:                sprintf(smb->last_error,"%d opening %s",errno,str);
        !           250:                close(file);
        !           251:                return(-3); 
        !           252:        }
        !           253:        setvbuf(smb->sha_fp,NULL,_IOFBF,2*1024);
        !           254:        return(0);
        !           255: }
        !           256: 
        !           257: void SMBCALL smb_close_ha(smb_t* smb)
        !           258: {
        !           259:        if(smb->sha_fp!=NULL)
        !           260:                fclose(smb->sha_fp);
        !           261:        smb->sha_fp=NULL;
        !           262: }
        !           263: 
        !           264: /****************************************************************************/
        !           265: /* If the parameter 'push' is non-zero, this function stores the currently  */
        !           266: /* open message base to the "virtual" smb stack. Up to SMB_STACK_LEN        */
        !           267: /* message bases may be stored (defined in SMBDEFS.H).                                         */
        !           268: /* The parameter 'op' is the operation to perform on the stack. Either      */
        !           269: /* SMB_STACK_PUSH, SMB_STACK_POP, or SMB_STACK_XCHNG                                           */
        !           270: /* If the operation is SMB_STACK_POP, this function restores a message base */
        !           271: /* previously saved with a SMB_STACK_PUSH call to this same function.          */
        !           272: /* If the operation is SMB_STACK_XCHNG, then the current message base is       */
        !           273: /* exchanged with the message base on the top of the stack (most recently      */
        !           274: /* pushed.                                                                                                                                     */
        !           275: /* If the current message base is not open, the SMB_STACK_PUSH and                     */
        !           276: /* SMB_STACK_XCHNG operations do nothing                                                                       */
        !           277: /* Returns 0 on success, non-zero if stack full.                            */
        !           278: /* If operation is SMB_STACK_POP or SMB_STACK_XCHNG, it always returns 0.      */
        !           279: /****************************************************************************/
        !           280: int SMBCALL smb_stack(smb_t* smb, int op)
        !           281: {
        !           282:        static char stack_file[SMB_STACK_LEN][128];
        !           283:        static FILE* stack_sdt[SMB_STACK_LEN],
        !           284:                                *stack_shd[SMB_STACK_LEN],
        !           285:                                *stack_sid[SMB_STACK_LEN],
        !           286:                                *stack_sda[SMB_STACK_LEN],
        !           287:                                *stack_sha[SMB_STACK_LEN];
        !           288:        static int      stack_idx;
        !           289:        char            tmp_file[128];
        !           290:        FILE            *tmp_sdt,
        !           291:                                *tmp_shd,
        !           292:                                *tmp_sid,
        !           293:                                *tmp_sda,
        !           294:                                *tmp_sha;
        !           295: 
        !           296:        if(op==SMB_STACK_PUSH) {
        !           297:                if(stack_idx>=SMB_STACK_LEN) {
        !           298:                        sprintf(smb->last_error,"SMB stack overflow");
        !           299:                        return(1);
        !           300:                }
        !           301:                if(smb->shd_fp==NULL || smb->sdt_fp==NULL || smb->sid_fp==NULL)
        !           302:                        return(0);        /* Msg base not open */
        !           303:                memcpy(stack_file[stack_idx],smb->file,128);
        !           304:                stack_sdt[stack_idx]=smb->sdt_fp;
        !           305:                stack_shd[stack_idx]=smb->shd_fp;
        !           306:                stack_sid[stack_idx]=smb->sid_fp;
        !           307:                stack_sda[stack_idx]=smb->sda_fp;
        !           308:                stack_sha[stack_idx]=smb->sha_fp;
        !           309:                stack_idx++;
        !           310:                return(0)        !           311:        }
        !           312:        /* pop or xchng */
        !           313:        if(!stack_idx)  /* Nothing on the stack, so do nothing */
        !           314:                return(0);
        !           315:        if(op==SMB_STACK_XCHNG) {
        !           316:                if(!smb->shd_fp)
        !           317:                        return(0);
        !           318:                memcpy(tmp_file,smb->file,128);
        !           319:                tmp_sdt=smb->sdt_fp;
        !           320:                tmp_shd=smb->shd_fp;
        !           321:                tmp_sid=smb->sid_fp;
        !           322:                tmp_sda=smb->sda_fp;
        !           323:                tmp_sha=smb->sha_fp; 
        !           324:        }
        !           325: 
        !           326:        stack_idx--;
        !           327:        memcpy(smb->file,stack_file[stack_idx],128);
        !           328:        smb->sdt_fp=stack_sdt[stack_idx];
        !           329:        smb->shd_fp=stack_shd[stack_idx];
        !           330:        smb->sid_fp=stack_sid[stack_idx];
        !           331:        smb->sda_fp=stack_sda[stack_idx];
        !           332:        smb->sha_fp=stack_sha[stack_idx];
        !           333:        if(op==SMB_STACK_XCHNG) {
        !           334:                stack_idx++;
        !           335:                memcpy(stack_file[stack_idx-1],tmp_file,128);
        !           336:                stack_sdt[stack_idx-1]=tmp_sdt;
        !           337:                stack_shd[stack_idx-1]=tmp_shd;
        !           338:                stack_sid[stack_idx-1]=tmp_sid;
        !           339:                stack_sda[stack_idx-1]=tmp_sda;
        !           340:                stack_sha[stack_idx-1]=tmp_sha; 
        !           341:        }
        !           342:        return(0);
        !           343: }
        !           344: 
        !           345: /****************************************************************************/
        !           346: /* Truncates header file                                                                                                       */
        !           347: /* Retrys for smb.retry_time number of seconds                                                         */
        !           348: /* Return 0 on success, non-zero otherwise                                                                     */
        !           349: /****************************************************************************/
        !           350: int SMBCALL smb_trunchdr(smb_t* smb)
        !           351: {
        !           352:        ulong   start=0;
        !           353: 
        !           354:        rewind(smb->shd_fp);
        !           355:        while(1) {
        !           356:                if(!chsize(fileno(smb->shd_fp),0L))
        !           357:                        break;
        !           358:                if(errno!=EACCES) {
        !           359:                        sprintf(smb->last_error,"%d changing header file size",errno);
        !           360:                        return(-1);
        !           361:                }
        !           362:                if(!start)
        !           363:                        start=time(NULL);
        !           364:                else
        !           365:                        if(time(NULL)-start>=smb->retry_time) {  /* Time-out */
        !           366:                                sprintf(smb->last_error,"timeout changing header file size");
        !           367:                                return(-2); 
        !           368:                        }
        !           369:        }
        !           370:        return(0);
        !           371: }
        !           372: 
        !           373: /*********************************/
        !           374: /* Message Base Header Functions */
        !           375: /*********************************/
        !           376: 
        !           377: /****************************************************************************/
        !           378: /* Attempts for smb.retry_time number of seconds to lock the msg base hdr      */
        !           379: /****************************************************************************/
        !           380: int SMBCALL smb_locksmbhdr(smb_t* smb)
        !           381: {
        !           382:        ulong   start=0;
        !           383: 
        !           384:        while(1) {
        !           385:                if(!lock(fileno(smb->shd_fp),0L,sizeof(smbhdr_t)+sizeof(smbstatus_t)))
        !           386:                        return(0);
        !           387:                if(!start)
        !           388:                        start=time(NULL);
        !           389:                else
        !           390:                        if(time(NULL)-start>=smb->retry_time) 
        !           391:                                break;                                          
        !           392:                /* In case we've already locked it */
        !           393:                unlock(fileno(smb->shd_fp),0L,sizeof(smbhdr_t)+sizeof(smbstatus_t)); 
        !           394:        }
        !           395:        sprintf(smb->last_error,"timeout locking header");
        !           396:        return(-1);
        !           397: }
        !           398: 
        !           399: /****************************************************************************/
        !           400: /* Read the SMB header from the header file and place into smb.status          */
        !           401: /****************************************************************************/
        !           402: int SMBCALL smb_getstatus(smb_t* smb)
        !           403: {
        !           404:        int     i;
        !           405: 
        !           406:        setvbuf(smb->shd_fp,smb->shd_buf,_IONBF,SHD_BLOCK_LEN);
        !           407:        clearerr(smb->shd_fp);
        !           408:        fseek(smb->shd_fp,sizeof(smbhdr_t),SEEK_SET);
        !           409:        i=fread(&(smb->status),1,sizeof(smbstatus_t),smb->shd_fp);
        !           410:        setvbuf(smb->shd_fp,smb->shd_buf,_IOFBF,SHD_BLOCK_LEN);
        !           411:        if(i==sizeof(smbstatus_t))
        !           412:                return(0);
        !           413:        sprintf(smb->last_error,"read %d instead of %d",i,sizeof(smbstatus_t));
        !           414:        return(1);
        !           415: }
        !           416: 
        !           417: /****************************************************************************/
        !           418: /* Writes message base header                                                                                          */
        !           419: /****************************************************************************/
        !           420: int SMBCALL smb_putstatus(smb_t* smb)
        !           421: {
        !           422:        int i;
        !           423: 
        !           424:        clearerr(smb->shd_fp);
        !           425:        fseek(smb->shd_fp,sizeof(smbhdr_t),SEEK_SET);
        !           426:        i=fwrite(&(smb->status),1,sizeof(smbstatus_t),smb->shd_fp);
        !           427:        fflush(smb->shd_fp);
        !           428:        if(i==sizeof(smbstatus_t))
        !           429:                return(0);
        !           430:        sprintf(smb->last_error,"wrote %d instead of %d",i,sizeof(smbstatus_t));
        !           431:        return(1);
        !           432: }
        !           433: 
        !           434: /****************************************************************************/
        !           435: /* Unlocks previously locks message base header                                                        */
        !           436: /****************************************************************************/
        !           437: int SMBCALL smb_unlocksmbhdr(smb_t* smb)
        !           438: {
        !           439:        return(unlock(fileno(smb->shd_fp),0L,sizeof(smbhdr_t)+sizeof(smbstatus_t)));
        !           440: }
        !           441: 
        !           442: /********************************/
        !           443: /* Individual Message Functions */
        !           444: /********************************/
        !           445: 
        !           446: /****************************************************************************/
        !           447: /* Attempts for smb.retry_time number of seconds to lock the hdr for 'msg'  */
        !           448: /****************************************************************************/
        !           449: int SMBCALL smb_lockmsghdr(smb_t* smb, smbmsg_t* msg)
        !           450: {
        !           451:        ulong   start=0;
        !           452: 
        !           453:        while(1) {
        !           454:                if(!lock(fileno(smb->shd_fp),msg->idx.offset,sizeof(msghdr_t)))
        !           455:                        return(0);
        !           456:                if(!start)
        !           457:                        start=time(NULL);
        !           458:                else
        !           459:                        if(time(NULL)-start>=smb->retry_time) 
        !           460:                                break;
        !           461:                /* In case we've already locked it */
        !           462:                unlock(fileno(smb->shd_fp),msg->idx.offset,sizeof(msghdr_t)); 
        !           463:        }
        !           464:        sprintf(smb->last_error,"timeout locking header");
        !           465:        return(-1);
        !           466: }
        !           467: 
        !           468: /****************************************************************************/
        !           469: /* Fills msg->idx with message index based on msg->hdr.number                          */
        !           470: /* OR if msg->hdr.number is 0, based on msg->offset (record offset).           */
        !           471: /* if msg.hdr.number does not equal 0, then msg->offset is filled too.         */
        !           472: /* Either msg->hdr.number or msg->offset must be initialized before            */
        !           473: /* calling this function                                                                                                       */
        !           474: /* Returns 1 if message number wasn't found, 0 if it was                    */
        !           475: /****************************************************************************/
        !           476: int SMBCALL smb_getmsgidx(smb_t* smb, smbmsg_t* msg)
        !           477: {
        !           478:        idxrec_t idx;
        !           479:        ulong    l,length,total,bot,top;
        !           480: 
        !           481:        clearerr(smb->sid_fp);
        !           482:        if(!msg->hdr.number) {
        !           483:                fseek(smb->sid_fp,msg->offset*sizeof(idxrec_t),SEEK_SET);
        !           484:                if(!fread(&msg->idx,sizeof(idxrec_t),1,smb->sid_fp)) {
        !           485:                        sprintf(smb->last_error,"reading index");
        !           486:                        return(1);
        !           487:                }
        !           488:                return(0)        !           489:        }
        !           490: 
        !           491:        length=filelength(fileno(smb->sid_fp));
        !           492:        if(!length) {
        !           493:                sprintf(smb->last_error,"invalid index file length: %ld",length);
        !           494:                return(1);
        !           495:        }
        !           496:        total=length/sizeof(idxrec_t);
        !           497:        if(!total) {
        !           498:                sprintf(smb->last_error,"invalid index file length: %ld",length);
        !           499:                return(1);
        !           500:        }
        !           501: 
        !           502:        bot=0;
        !           503:        top=total;
        !           504:        l=total/2; /* Start at middle index */
        !           505:        while(1) {
        !           506:                fseek(smb->sid_fp,l*sizeof(idxrec_t),SEEK_SET);
        !           507:                if(!fread(&idx,sizeof(idxrec_t),1,smb->sid_fp)) {
        !           508:                        sprintf(smb->last_error,"reading index");
        !           509:                        return(1);
        !           510:                }
        !           511:                if(bot==top-1 && idx.number!=msg->hdr.number) {
        !           512:                        sprintf(smb->last_error,"msg %d not found",msg->hdr.number);
        !           513:                        return(1);
        !           514:                }
        !           515:                if(idx.number>msg->hdr.number) {
        !           516:                        top=l;
        !           517:                        l=bot+((top-bot)/2);
        !           518:                        continue; 
        !           519:                }
        !           520:                if(idx.number<msg->hdr.number) {
        !           521:                        bot=l;
        !           522:                        l=top-((top-bot)/2);
        !           523:                        continue; 
        !           524:                }
        !           525:                break; 
        !           526:        }
        !           527:        msg->idx=idx;
        !           528:        msg->offset=l;
        !           529:        return(0);
        !           530: }
        !           531: 
        !           532: /****************************************************************************/
        !           533: /* Reads the last index record in the open message base                                        */
        !           534: /****************************************************************************/
        !           535: int SMBCALL smb_getlastidx(smb_t* smb, idxrec_t *idx)
        !           536: {
        !           537:        long length;
        !           538: 
        !           539:        clearerr(smb->sid_fp);
        !           540:        length=filelength(fileno(smb->sid_fp));
        !           541:        if(length<sizeof(idxrec_t)) {
        !           542:                sprintf(smb->last_error,"invalid index file length: %ld",length);
        !           543:                return(-1);
        !           544:        }
        !           545:        fseek(smb->sid_fp,length-sizeof(idxrec_t),SEEK_SET);
        !           546:        if(!fread(idx,sizeof(idxrec_t),1,smb->sid_fp)) {
        !           547:                sprintf(smb->last_error,"reading index");
        !           548:                return(-2);
        !           549:        }
        !           550:        return(0);
        !           551: }
        !           552: 
        !           553: /****************************************************************************/
        !           554: /* Figures out the total length of the header record for 'msg'              */
        !           555: /* Returns length                                                                                                                      */
        !           556: /****************************************************************************/
        !           557: uint SMBCALL smb_getmsghdrlen(smbmsg_t* msg)
        !           558: {
        !           559:        int i;
        !           560: 
        !           561:        /* fixed portion */
        !           562:        msg->hdr.length=sizeof(msghdr_t);
        !           563:        /* data fields */
        !           564:        msg->hdr.length+=msg->hdr.total_dfields*sizeof(dfield_t);
        !           565:        /* header fields */
        !           566:        for(i=0;i<msg->total_hfields;i++) {
        !           567:                msg->hdr.length+=sizeof(hfield_t);
        !           568:                msg->hdr.length+=msg->hfield[i].length; 
        !           569:        }
        !           570:        return(msg->hdr.length);
        !           571: }
        !           572: 
        !           573: /****************************************************************************/
        !           574: /* Figures out the total length of the data buffer for 'msg'                */
        !           575: /* Returns length                                                                                                                      */
        !           576: /****************************************************************************/
        !           577: ulong SMBCALL smb_getmsgdatlen(smbmsg_t* msg)
        !           578: {
        !           579:        int i;
        !           580:        ulong length=0L;
        !           581: 
        !           582:        for(i=0;i<msg->hdr.total_dfields;i++)
        !           583:                length+=msg->dfield[i].length;
        !           584:        return(length);
        !           585: }
        !           586: 
        !           587: /****************************************************************************/
        !           588: /* Read header information into 'msg' structure                             */
        !           589: /* msg->idx.offset must be set before calling this function                            */
        !           590: /* Must call smb_freemsgmem() to free memory allocated for var len strs        */
        !           591: /* Returns 0 on success, non-zero if error                                                                     */
        !           592: /****************************************************************************/
        !           593: int SMBCALL smb_getmsghdr(smb_t* smb, smbmsg_t* msg)
        !           594: {
        !           595:        void    *vp,**vpp;
        !           596:        ushort  i;
        !           597:        ulong   l,offset;
        !           598:        idxrec_t idx;
        !           599: 
        !           600:        rewind(smb->shd_fp);
        !           601:        fseek(smb->shd_fp,msg->idx.offset,SEEK_SET);
        !           602:        idx=msg->idx;
        !           603:        offset=msg->offset;
        !           604:        memset(msg,0,sizeof(smbmsg_t));
        !           605:        msg->idx=idx;
        !           606:        msg->offset=offset;
        !           607:        if(!fread(&msg->hdr,sizeof(msghdr_t),1,smb->shd_fp)) {
        !           608:                sprintf(smb->last_error,"reading msg header");
        !           609:                return(-1);
        !           610:        }
        !           611:        if(memcmp(msg->hdr.id,"SHD\x1a",4)) {
        !           612:                sprintf(smb->last_error,"corrupt header id: %.4s",msg->hdr.id);
        !           613:                return(-2);
        !           614:        }
        !           615:        if(msg->hdr.version<0x110) {
        !           616:                sprintf(smb->last_error,"insufficient header version: %X",msg->hdr.version);
        !           617:                return(-9);
        !           618:        }
        !           619:        l=sizeof(msghdr_t);
        !           620:        if(msg->hdr.total_dfields && (msg->dfield
        !           621:                =(dfield_t *)MALLOC(sizeof(dfield_t)*msg->hdr.total_dfields))==NULL) {
        !           622:                smb_freemsgmem(msg);
        !           623:                sprintf(smb->last_error,"malloc failure of %d bytes for %d data fields"
        !           624:                        ,sizeof(dfield_t)*msg->hdr.total_dfields, msg->hdr.total_dfields);
        !           625:                return(-3); 
        !           626:        }
        !           627:        i=0;
        !           628:        while(i<msg->hdr.total_dfields && l<msg->hdr.length) {
        !           629:                if(!fread(&msg->dfield[i],sizeof(dfield_t),1,smb->shd_fp)) {
        !           630:                        smb_freemsgmem(msg);
        !           631:                        sprintf(smb->last_error,"reading data field %d",i);
        !           632:                        return(-4); 
        !           633:                }
        !           634:                i++;
        !           635:                l+=sizeof(dfield_t); 
        !           636:        }
        !           637:        if(i<msg->hdr.total_dfields) {
        !           638:                smb_freemsgmem(msg);
        !           639:                sprintf(smb->last_error,"insufficient data fields read (%d instead of %d)"
        !           640:                        ,i,msg->hdr.total_dfields);
        !           641:                return(-8); 
        !           642:        }
        !           643:        while(l<msg->hdr.length) {
        !           644:                i=msg->total_hfields;
        !           645:                if((vpp=(void* *)REALLOC(msg->hfield_dat,sizeof(void* )*(i+1)))==NULL) {
        !           646:                        smb_freemsgmem(msg);
        !           647:                        sprintf(smb->last_error
        !           648:                                ,"realloc failure of %d bytes for header field data"
        !           649:                                ,sizeof(void*)*(i+1));
        !           650:                        return(-3); 
        !           651:                }
        !           652:                msg->hfield_dat=vpp;
        !           653:                if((vp=(hfield_t *)REALLOC(msg->hfield,sizeof(hfield_t)*(i+1)))==NULL) {
        !           654:                        smb_freemsgmem(msg);
        !           655:                        sprintf(smb->last_error
        !           656:                                ,"realloc failure of %d bytes for header fields"
        !           657:                                ,sizeof(hfield_t)*(i+1));
        !           658:                        return(-3); 
        !           659:                }
        !           660:                msg->hfield=vp;
        !           661:                msg->total_hfields++;
        !           662:                if(!fread(&msg->hfield[i],sizeof(hfield_t),1,smb->shd_fp)) {
        !           663:                        smb_freemsgmem(msg);
        !           664:                        sprintf(smb->last_error,"reading header field");
        !           665:                        return(-5); 
        !           666:                }
        !           667:                l+=sizeof(hfield_t);
        !           668:                if((msg->hfield_dat[i]=(char*)MALLOC(msg->hfield[i].length+1))
        !           669:                        ==NULL) {                       /* Allocate 1 extra for NULL terminator */
        !           670:                        sprintf(smb->last_error
        !           671:                                ,"malloc failure of %d bytes for header field %d"
        !           672:                                ,msg->hfield[i].length+1, i);
        !           673:                        smb_freemsgmem(msg);  /* or 0 length field */
        !           674:                        return(-3); 
        !           675:                }
        !           676:                memset(msg->hfield_dat[i],0,msg->hfield[i].length+1);  /* init to NULL */
        !           677:                if(msg->hfield[i].length
        !           678:                        && !fread(msg->hfield_dat[i],msg->hfield[i].length,1,smb->shd_fp)) {
        !           679:                        smb_freemsgmem(msg);
        !           680:                        sprintf(smb->last_error,"reading header field data");
        !           681:                        return(-6); 
        !           682:                }
        !           683:                switch(msg->hfield[i].type) {   /* convenience variables */
        !           684:                        case SENDER:
        !           685:                                if(!msg->from) {
        !           686:                                        msg->from=msg->hfield_dat[i];
        !           687:                                        break; 
        !           688:                                }
        !           689:                        case FORWARDED:         /* fall through */
        !           690:                                msg->forwarded=1;
        !           691:                                break;
        !           692:                        case SENDERAGENT:
        !           693:                                if(!msg->forwarded)
        !           694:                                        msg->from_agent=*(ushort *)msg->hfield_dat[i];
        !           695:                                break;
        !           696:                        case SENDEREXT:
        !           697:                                if(!msg->forwarded)
        !           698:                                        msg->from_ext=msg->hfield_dat[i];
        !           699:                                break;
        !           700:                        case SENDERNETTYPE:
        !           701:                                if(!msg->forwarded)
        !           702:                                        msg->from_net.type=*(ushort *)msg->hfield_dat[i];
        !           703:                                break;
        !           704:                        case SENDERNETADDR:
        !           705:                                if(!msg->forwarded)
        !           706:                                        msg->from_net.addr=msg->hfield_dat[i];
        !           707:                                break;
        !           708:                        case REPLYTO:
        !           709:                                msg->replyto=msg->hfield_dat[i];
        !           710:                                break;
        !           711:                        case REPLYTOEXT:
        !           712:                                msg->replyto_ext=msg->hfield_dat[i];
        !           713:                                break;
        !           714:                        case REPLYTOAGENT:
        !           715:                                msg->replyto_agent=*(ushort *)msg->hfield_dat[i];
        !           716:                                break;
        !           717:                        case REPLYTONETTYPE:
        !           718:                                msg->replyto_net.type=*(ushort *)msg->hfield_dat[i];
        !           719:                                break;
        !           720:                        case REPLYTONETADDR:
        !           721:                                msg->replyto_net.addr=msg->hfield_dat[i];
        !           722:                                break;
        !           723:                        case RECIPIENT:
        !           724:                                msg->to=msg->hfield_dat[i];
        !           725:                                break;
        !           726:                        case RECIPIENTEXT:
        !           727:                                msg->to_ext=msg->hfield_dat[i];
        !           728:                                break;
        !           729:                        case RECIPIENTAGENT:
        !           730:                                msg->to_agent=*(ushort *)msg->hfield_dat[i];
        !           731:                                break;
        !           732:                        case RECIPIENTNETTYPE:
        !           733:                                msg->to_net.type=*(ushort *)msg->hfield_dat[i];
        !           734:                                break;
        !           735:                        case RECIPIENTNETADDR:
        !           736:                                msg->to_net.addr=msg->hfield_dat[i];
        !           737:                                break;
        !           738:                        case SUBJECT:
        !           739:                                msg->subj=msg->hfield_dat[i];
        !           740:                                break; 
        !           741:                }
        !           742:                l+=msg->hfield[i].length; 
        !           743:        }
        !           744: 
        !           745:        if(!msg->from || !msg->to || !msg->subj) {
        !           746:                sprintf(smb->last_error,"missing required header field (from/to/subj)");
        !           747:                smb_freemsgmem(msg);
        !           748:                return(-7); 
        !           749:        }
        !           750:        return(0);
        !           751: }
        !           752: 
        !           753: /****************************************************************************/
        !           754: /* Frees memory allocated for 'msg'                                         */
        !           755: /****************************************************************************/
        !           756: void SMBCALL smb_freemsgmem(smbmsg_t* msg)
        !           757: {
        !           758:        ushort  i;
        !           759: 
        !           760:        if(msg->dfield) {
        !           761:                FREE(msg->dfield);
        !           762:                msg->dfield=NULL;
        !           763:        }
        !           764:        for(i=0;i<msg->total_hfields;i++)
        !           765:                if(msg->hfield_dat[i]) {
        !           766:                        FREE(msg->hfield_dat[i]);
        !           767:                        msg->hfield_dat[i]=NULL;
        !           768:                }
        !           769:        msg->total_hfields=0;
        !           770:        if(msg->hfield) {
        !           771:                FREE(msg->hfield);
        !           772:                msg->hfield=NULL;
        !           773:        }
        !           774:        if(msg->hfield_dat) {
        !           775:                FREE(msg->hfield_dat);
        !           776:                msg->hfield_dat=NULL;
        !           777:        }
        !           778: }
        !           779: 
        !           780: /****************************************************************************/
        !           781: /* Copies memory allocated for 'srcmsg' to 'msg'                                                       */
        !           782: /****************************************************************************/
        !           783: int SMBCALL smb_copymsgmem(smbmsg_t* msg, smbmsg_t* srcmsg)
        !           784: {
        !           785:        int i;
        !           786: 
        !           787:        memcpy(msg,srcmsg,sizeof(smbmsg_t));
        !           788: 
        !           789:        /* data field types/lengths */
        !           790:        if((msg->dfield=MALLOC(msg->hdr.total_dfields*sizeof(dfield_t)))==NULL)
        !           791:                return(1);
        !           792:        memcpy(msg->dfield,srcmsg->dfield,msg->hdr.total_dfields*sizeof(dfield_t));
        !           793: 
        !           794:        /* header field types/lengths */
        !           795:        if((msg->hfield=MALLOC(msg->total_hfields*sizeof(hfield_t)))==NULL)
        !           796:                return(2);
        !           797:        memcpy(msg->hfield,srcmsg->hfield,msg->total_hfields*sizeof(hfield_t));
        !           798: 
        !           799:        /* header field data */
        !           800:        if((msg->hfield_dat=MALLOC(msg->total_hfields*sizeof(void*)))==NULL)
        !           801:                return(3);
        !           802: 
        !           803:        for(i=0;i<msg->total_hfields;i++) {
        !           804:                if((msg->hfield_dat[i]=(char*)MALLOC(msg->hfield[i].length))==NULL)
        !           805:                        return(4);
        !           806:                memcpy(msg->hfield_dat[i],srcmsg->hfield_dat[i],msg->hfield[i].length);
        !           807:        }
        !           808: 
        !           809:        return(0);
        !           810: }
        !           811: 
        !           812: /****************************************************************************/
        !           813: /* Unlocks header for 'msg'                                                 */
        !           814: /****************************************************************************/
        !           815: int SMBCALL smb_unlockmsghdr(smb_t* smb, smbmsg_t* msg)
        !           816: {
        !           817:        return(unlock(fileno(smb->shd_fp),msg->idx.offset,sizeof(msghdr_t)));
        !           818: }
        !           819: 
        !           820: 
        !           821: /****************************************************************************/
        !           822: /* Adds a header field to the 'msg' structure (in memory only)              */
        !           823: /****************************************************************************/
        !           824: int SMBCALL smb_hfield(smbmsg_t* msg, ushort type, ushort length, void* data)
        !           825: {
        !           826:        void* vp,**vpp;
        !           827:        int i;
        !           828: 
        !           829:        i=msg->total_hfields;
        !           830:        if((vp=(hfield_t *)REALLOC(msg->hfield,sizeof(hfield_t)*(i+1)))==NULL) 
        !           831:                return(1);
        !           832: 
        !           833:        msg->hfield=vp;
        !           834:        if((vpp=(void* *)REALLOC(msg->hfield_dat,sizeof(void* )*(i+1)))==NULL) 
        !           835:                return(2);
        !           836:        
        !           837:        msg->hfield_dat=vpp;
        !           838:        msg->total_hfields++;
        !           839:        msg->hfield[i].type=type;
        !           840:        msg->hfield[i].length=length;
        !           841:        if(length) {
        !           842:                if((msg->hfield_dat[i]=(void* )MALLOC(length))==NULL) 
        !           843:                        return(4);
        !           844:                memcpy(msg->hfield_dat[i],data,length); 
        !           845:        }
        !           846:        else
        !           847:                msg->hfield_dat[i]=NULL;
        !           848:        return(0);
        !           849: }
        !           850: 
        !           851: /****************************************************************************/
        !           852: /* Adds a data field to the 'msg' structure (in memory only)                */
        !           853: /* Automatically figures out the offset into the data buffer from existing     */
        !           854: /* dfield lengths                                                                                                                      */
        !           855: /****************************************************************************/
        !           856: int SMBCALL smb_dfield(smbmsg_t* msg, ushort type, ulong length)
        !           857: {
        !           858:        void* vp;
        !           859:        int i,j;
        !           860: 
        !           861:        i=msg->hdr.total_dfields;
        !           862:        if((vp=(dfield_t *)REALLOC(msg->dfield,sizeof(dfield_t)*(i+1)))==NULL) 
        !           863:                return(1);
        !           864:        
        !           865:        msg->dfield=vp;
        !           866:        msg->hdr.total_dfields++;
        !           867:        msg->dfield[i].type=type;
        !           868:        msg->dfield[i].length=length;
        !           869:        for(j=msg->dfield[i].offset=0;j<i;j++)
        !           870:                msg->dfield[i].offset+=msg->dfield[j].length;
        !           871:        return(0);
        !           872: }
        !           873: 
        !           874: /****************************************************************************/
        !           875: /* Checks CRC history file for duplicate crc. If found, returns 1.                     */
        !           876: /* If no dupe, adds to CRC history and returns 0, or negative if error.        */
        !           877: /****************************************************************************/
        !           878: int SMBCALL smb_addcrc(smb_t* smb, ulong crc)
        !           879: {
        !           880:        char    str[128];
        !           881:        int     file;
        !           882:        long    length;
        !           883:        ulong   l,*buf;
        !           884:        ulong   start=0;
        !           885: 
        !           886:        if(!smb->status.max_crcs)
        !           887:                return(0);
        !           888: 
        !           889:        sprintf(str,"%s.sch",smb->file);
        !           890:        while(1) {
        !           891:                if((file=sopen(str,O_RDWR|O_CREAT|O_BINARY,SH_DENYRW))!=-1)
        !           892:                        break;
        !           893:                if(errno!=EACCES) {
        !           894:                        sprintf(smb->last_error,"%d opening %s", errno, str);
        !           895:                        return(-1);
        !           896:                }
        !           897:                if(!start)
        !           898:                        start=time(NULL);
        !           899:                else
        !           900:                        if(time(NULL)-start>=smb->retry_time) {
        !           901:                                sprintf(smb->last_error,"timeout opening %s", str);
        !           902:                                return(-2); 
        !           903:                        }
        !           904:        }
        !           905: 
        !           906:        length=filelength(file);
        !           907:        if(length<0L) {
        !           908:                close(file);
        !           909:                sprintf(smb->last_error,"invalid file length: %ld", length);
        !           910:                return(-4); 
        !           911:        }
        !           912:        if((buf=(ulong*)MALLOC(smb->status.max_crcs*4))==NULL) {
        !           913:                close(file);
        !           914:                sprintf(smb->last_error
        !           915:                        ,"malloc failure of %d bytes"
        !           916:                        ,smb->status.max_crcs*4);
        !           917:                return(-3); 
        !           918:        }
        !           919:        if((ulong)length>=smb->status.max_crcs*4L) { /* Reached or exceeds max crcs */
        !           920:                read(file,buf,smb->status.max_crcs*4);
        !           921:                for(l=0;l<smb->status.max_crcs;l++)
        !           922:                        if(crc==buf[l])
        !           923:                                break;
        !           924:                if(l<smb->status.max_crcs) {                            /* Dupe CRC found */
        !           925:                        close(file);
        !           926:                        FREE(buf);
        !           927:                        return(1)        !           928:                }
        !           929:                chsize(file,0L);                                /* truncate it */
        !           930:                lseek(file,0L,SEEK_SET);
        !           931:                write(file,buf+4,(smb->status.max_crcs-1)*4); 
        !           932:        }
        !           933: 
        !           934:        else if(length/4) {                                     /* Less than max crcs */
        !           935:                read(file,buf,length);
        !           936:                for(l=0;l<(ulong)(length/4);l++)
        !           937:                        if(crc==buf[l])
        !           938:                                break;
        !           939:                if(l<(ulong)(length/4L)) {                                      /* Dupe CRC found */
        !           940:                        close(file);
        !           941:                        FREE(buf);
        !           942:                        return(1)        !           943:                } 
        !           944:        }
        !           945: 
        !           946:        lseek(file,0L,SEEK_END);
        !           947:        write(file,&crc,4);                        /* Write to the end */
        !           948:        FREE(buf);
        !           949:        close(file);
        !           950:        return(0);
        !           951: }
        !           952: 
        !           953: /****************************************************************************/
        !           954: /* Creates a new message header record in the header file.                                     */
        !           955: /* If storage is SMB_SELFPACK, self-packing conservative allocation is used */
        !           956: /* If storage is SMB_FASTALLOC, fast allocation is used                                        */
        !           957: /* If storage is SMB_HYPERALLOC, no allocation tables are used (fastest)       */
        !           958: /****************************************************************************/
        !           959: int SMBCALL smb_addmsghdr(smb_t* smb, smbmsg_t* msg, int storage)
        !           960: {
        !           961:        int i;
        !           962:        long l;
        !           963: 
        !           964:        if(smb_locksmbhdr(smb))
        !           965:                return(1);
        !           966:        if(smb_getstatus(smb))
        !           967:                return(2);
        !           968: 
        !           969:        if(storage!=SMB_HYPERALLOC && (i=smb_open_ha(smb))!=0)
        !           970:                return(i);
        !           971: 
        !           972:        msg->hdr.length=smb_getmsghdrlen(msg);
        !           973:        if(storage==SMB_HYPERALLOC)
        !           974:                l=smb_hallochdr(smb);
        !           975:        else if(storage==SMB_FASTALLOC)
        !           976:                l=smb_fallochdr(smb,msg->hdr.length);
        !           977:        else
        !           978:                l=smb_allochdr(smb,msg->hdr.length);
        !           979:        if(l==-1L) {
        !           980:                smb_unlocksmbhdr(smb);
        !           981:                smb_close_ha(smb);
        !           982:                return(-1); 
        !           983:        }
        !           984: 
        !           985:        smb->status.last_msg++;
        !           986:        msg->idx.number=msg->hdr.number=smb->status.last_msg;
        !           987:        msg->idx.offset=smb->status.header_offset+l;
        !           988:        msg->idx.time=msg->hdr.when_imported.time;
        !           989:        msg->idx.attr=msg->hdr.attr;
        !           990:        msg->offset=smb->status.total_msgs;
        !           991:        smb->status.total_msgs++;
        !           992:        smb_putstatus(smb);
        !           993: 
        !           994:        if(storage!=SMB_HYPERALLOC)
        !           995:                smb_close_ha(smb);
        !           996:        i=smb_putmsg(smb,msg);
        !           997:        smb_unlocksmbhdr(smb);
        !           998:        return(i);
        !           999: }
        !          1000: 
        !          1001: /****************************************************************************/
        !          1002: /* Writes both header and index information for msg 'msg'                   */
        !          1003: /****************************************************************************/
        !          1004: int SMBCALL smb_putmsg(smb_t* smb, smbmsg_t* msg)
        !          1005: {
        !          1006:        int i;
        !          1007: 
        !          1008:        i=smb_putmsghdr(smb,msg);
        !          1009:        if(i)
        !          1010:                return(i);
        !          1011:        return(smb_putmsgidx(smb,msg));
        !          1012: }
        !          1013: 
        !          1014: /****************************************************************************/
        !          1015: /* Writes index information for 'msg'                                       */
        !          1016: /* msg->idx                                                                                                                             */
        !          1017: /* and msg->offset must be set prior to calling to this function                        */
        !          1018: /* Returns 0 if everything ok                                               */
        !          1019: /****************************************************************************/
        !          1020: int SMBCALL smb_putmsgidx(smb_t* smb, smbmsg_t* msg)
        !          1021: {
        !          1022: 
        !          1023:        clearerr(smb->sid_fp);
        !          1024:        fseek(smb->sid_fp,msg->offset*sizeof(idxrec_t),SEEK_SET);
        !          1025:        if(!fwrite(&msg->idx,sizeof(idxrec_t),1,smb->sid_fp)) {
        !          1026:                sprintf(smb->last_error,"writing index");
        !          1027:                return(1);
        !          1028:        }
        !          1029:        fflush(smb->sid_fp);
        !          1030:        return(0);
        !          1031: }
        !          1032: 
        !          1033: /****************************************************************************/
        !          1034: /* Writes header information for 'msg'                                      */
        !          1035: /* msg->hdr.length                                                                                                                      */
        !          1036: /* msg->idx.offset                                                                                                                      */
        !          1037: /* and msg->offset must be set prior to calling to this function                        */
        !          1038: /* Returns 0 if everything ok                                               */
        !          1039: /****************************************************************************/
        !          1040: int SMBCALL smb_putmsghdr(smb_t* smb, smbmsg_t* msg)
        !          1041: {
        !          1042:        ushort  i;
        !          1043:        ulong   l;
        !          1044: 
        !          1045:        clearerr(smb->shd_fp);
        !          1046:        if(fseek(smb->shd_fp,msg->idx.offset,SEEK_SET)) {
        !          1047:                sprintf(smb->last_error,"seeking to %d in index",msg->idx.offset);
        !          1048:                return(-1);
        !          1049:        }
        !          1050: 
        !          1051:        /************************************************/
        !          1052:        /* Write the fixed portion of the header record */
        !          1053:        /************************************************/
        !          1054:        if(!fwrite(&msg->hdr,sizeof(msghdr_t),1,smb->shd_fp)) {
        !          1055:                sprintf(smb->last_error,"writing fixed portion of header record");
        !          1056:                return(-2);
        !          1057:        }
        !          1058: 
        !          1059:        /************************************************/
        !          1060:        /* Write the data fields (each is fixed length) */
        !          1061:        /************************************************/
        !          1062:        for(i=0;i<msg->hdr.total_dfields;i++)
        !          1063:                if(!fwrite(&msg->dfield[i],sizeof(dfield_t),1,smb->shd_fp)) {
        !          1064:                        sprintf(smb->last_error,"writing data field");
        !          1065:                        return(-3);
        !          1066:                }
        !          1067: 
        !          1068:        /*******************************************/
        !          1069:        /* Write the variable length header fields */
        !          1070:        /*******************************************/
        !          1071:        for(i=0;i<msg->total_hfields;i++) {
        !          1072:                if(!fwrite(&msg->hfield[i],sizeof(hfield_t),1,smb->shd_fp)) {
        !          1073:                        sprintf(smb->last_error,"writing header field");
        !          1074:                        return(-4);
        !          1075:                }
        !          1076:                if(msg->hfield[i].length                                         /* more then 0 bytes long */
        !          1077:                        && !fwrite(msg->hfield_dat[i],msg->hfield[i].length,1,smb->shd_fp)) {
        !          1078:                        sprintf(smb->last_error,"writing header field data");
        !          1079:                        return(-5); 
        !          1080:                }
        !          1081:        }
        !          1082: 
        !          1083:        l=smb_getmsghdrlen(msg);
        !          1084:        while(l%SHD_BLOCK_LEN) {
        !          1085:                if(fputc(0,smb->shd_fp)==EOF) {
        !          1086:                        sprintf(smb->last_error,"padding header block");
        !          1087:                        return(-6);                        /* pad block with NULL */
        !          1088:                }
        !          1089:                l++; 
        !          1090:        }
        !          1091:        fflush(smb->shd_fp);
        !          1092:        return(0);
        !          1093: }
        !          1094: 
        !          1095: /****************************************************************************/
        !          1096: /* Creates a sub-board's initial header file                                */
        !          1097: /* Truncates and deletes other associated SMB files                                            */
        !          1098: /****************************************************************************/
        !          1099: int SMBCALL smb_create(smb_t* smb)
        !          1100: {
        !          1101:     char        str[128];
        !          1102:        smbhdr_t        hdr;
        !          1103: 
        !          1104:        if(filelength(fileno(smb->shd_fp))>=sizeof(smbhdr_t)+sizeof(smbstatus_t)
        !          1105:                && smb_locksmbhdr(smb))  /* header exists, so lock it */
        !          1106:                return(1);
        !          1107:        memset(&hdr,0,sizeof(smbhdr_t));
        !          1108:        memcpy(hdr.id,"SMB\x1a",4);     /* <S> <M> <B> <^Z> */
        !          1109:        hdr.version=SMB_VERSION;
        !          1110:        hdr.length=sizeof(smbhdr_t)+sizeof(smbstatus_t);
        !          1111:        smb->status.last_msg=smb->status.total_msgs=0;
        !          1112:        smb->status.header_offset=sizeof(smbhdr_t)+sizeof(smbstatus_t);
        !          1113:        rewind(smb->shd_fp);
        !          1114:        fwrite(&hdr,1,sizeof(smbhdr_t),smb->shd_fp);
        !          1115:        fwrite(&(smb->status),1,sizeof(smbstatus_t),smb->shd_fp);
        !          1116:        rewind(smb->shd_fp);
        !          1117:        chsize(fileno(smb->shd_fp),sizeof(smbhdr_t)+sizeof(smbstatus_t));
        !          1118:        fflush(smb->shd_fp);
        !          1119: 
        !          1120:        rewind(smb->sdt_fp);
        !          1121:        chsize(fileno(smb->sdt_fp),0L);
        !          1122:        rewind(smb->sid_fp);
        !          1123:        chsize(fileno(smb->sid_fp),0L);
        !          1124: 
        !          1125:        sprintf(str,"%s.sda",smb->file);
        !          1126:        remove(str);                                            /* if it exists, delete it */
        !          1127:        sprintf(str,"%s.sha",smb->file);
        !          1128:        remove(str);                        /* if it exists, delete it */
        !          1129:        sprintf(str,"%s.sch",smb->file);
        !          1130:        remove(str);
        !          1131:        smb_unlocksmbhdr(smb);
        !          1132:        return(0);
        !          1133: }
        !          1134: 
        !          1135: /****************************************************************************/
        !          1136: /* Returns number of data blocks required to store "length" amount of data  */
        !          1137: /****************************************************************************/
        !          1138: ulong SMBCALL smb_datblocks(ulong length)
        !          1139: {
        !          1140:        ulong blocks;
        !          1141: 
        !          1142:        blocks=length/SDT_BLOCK_LEN;
        !          1143:        if(length%SDT_BLOCK_LEN)
        !          1144:                blocks++;
        !          1145:        return(blocks);
        !          1146: }
        !          1147: 
        !          1148: /****************************************************************************/
        !          1149: /* Returns number of header blocks required to store "length" size header   */
        !          1150: /****************************************************************************/
        !          1151: ulong SMBCALL smb_hdrblocks(ulong length)
        !          1152: {
        !          1153:        ulong blocks;
        !          1154: 
        !          1155:        blocks=length/SHD_BLOCK_LEN;
        !          1156:        if(length%SHD_BLOCK_LEN)
        !          1157:                blocks++;
        !          1158:        return(blocks);
        !          1159: }
        !          1160: 
        !          1161: /****************************************************************************/
        !          1162: /* Finds unused space in data file based on block allocation table and         */
        !          1163: /* marks space as used in allocation table.                                 */
        !          1164: /* File must be opened read/write DENY ALL                                                                     */
        !          1165: /* Returns offset to beginning of data (in bytes, not blocks)                          */
        !          1166: /* Assumes smb_open_da() has been called                                                                       */
        !          1167: /* smb_close_da() should be called after                                                                       */
        !          1168: /* Returns negative on error                                                                                           */
        !          1169: /****************************************************************************/
        !          1170: long SMBCALL smb_allocdat(smb_t* smb, ulong length, ushort headers)
        !          1171: {
        !          1172:     ushort  i,j;
        !          1173:        ulong   l,blocks,offset=0L;
        !          1174: 
        !          1175:        blocks=smb_datblocks(length);
        !          1176:        j=0;    /* j is consecutive unused block counter */
        !          1177:        fflush(smb->sda_fp);
        !          1178:        rewind(smb->sda_fp);
        !          1179:        while(!feof(smb->sda_fp)) {
        !          1180:                if(!fread(&i,2,1,smb->sda_fp))
        !          1181:                        break;
        !          1182:                offset+=SDT_BLOCK_LEN;
        !          1183:                if(!i) j++;
        !          1184:                else   j=0;
        !          1185:                if(j==blocks) {
        !          1186:                        offset-=(blocks*SDT_BLOCK_LEN);
        !          1187:                        break; 
        !          1188:                } 
        !          1189:        }
        !          1190:        clearerr(smb->sda_fp);
        !          1191:        fseek(smb->sda_fp,(offset/SDT_BLOCK_LEN)*2L,SEEK_SET);
        !          1192:        for(l=0;l<blocks;l++)
        !          1193:                if(!fwrite(&headers,2,1,smb->sda_fp)) {
        !          1194:                        sprintf(smb->last_error,"writing allocation bytes");
        !          1195:                        return(-1);
        !          1196:                }
        !          1197:        fflush(smb->sda_fp);
        !          1198:        return(offset);
        !          1199: }
        !          1200: 
        !          1201: /****************************************************************************/
        !          1202: /* Allocates space for data, but doesn't search for unused blocks           */
        !          1203: /* Returns negative on error                                                                                           */
        !          1204: /****************************************************************************/
        !          1205: long SMBCALL smb_fallocdat(smb_t* smb, ulong length, ushort headers)
        !          1206: {
        !          1207:        ulong   l,blocks,offset;
        !          1208: 
        !          1209:        fflush(smb->sda_fp);
        !          1210:        clearerr(smb->sda_fp);
        !          1211:        blocks=smb_datblocks(length);
        !          1212:        fseek(smb->sda_fp,0L,SEEK_END);
        !          1213:        offset=(ftell(smb->sda_fp)/2L)*SDT_BLOCK_LEN;
        !          1214:        for(l=0;l<blocks;l++)
        !          1215:                if(!fwrite(&headers,2,1,smb->sda_fp))
        !          1216:                        break;
        !          1217:        fflush(smb->sda_fp);
        !          1218:        if(l<blocks) {
        !          1219:                sprintf(smb->last_error,"writing allocation bytes");
        !          1220:                return(-1L);
        !          1221:        }
        !          1222:        return(offset);
        !          1223: }
        !          1224: 
        !          1225: /****************************************************************************/
        !          1226: /* De-allocates space for data                                                                                         */
        !          1227: /* Returns non-zero on error                                                                                           */
        !          1228: /****************************************************************************/
        !          1229: int SMBCALL smb_freemsgdat(smb_t* smb, ulong offset, ulong length
        !          1230:                        , ushort headers)
        !          1231: {
        !          1232:        int             da_opened=0;
        !          1233:        ushort  i;
        !          1234:        ulong   l,blocks;
        !          1235: 
        !          1236:        blocks=smb_datblocks(length);
        !          1237: 
        !          1238:        if(smb->sda_fp==NULL) {
        !          1239:                if((i=smb_open_da(smb))!=0)
        !          1240:                        return(i);
        !          1241:                da_opened=1;
        !          1242:        }
        !          1243: 
        !          1244:        clearerr(smb->sda_fp);
        !          1245:        for(l=0;l<blocks;l++) {
        !          1246:                if(fseek(smb->sda_fp,((offset/SDT_BLOCK_LEN)+l)*2L,SEEK_SET)) {
        !          1247:                        sprintf(smb->last_error
        !          1248:                                ,"seeking to %ld of allocation file"
        !          1249:                                ,((offset/SDT_BLOCK_LEN)+l)*2L);
        !          1250:                        return(1);
        !          1251:                }
        !          1252:                if(!fread(&i,2,1,smb->sda_fp)) {
        !          1253:                        sprintf(smb->last_error,"reading allocation bytes");
        !          1254:                        return(2);
        !          1255:                }
        !          1256:                if(headers>i)
        !          1257:                        i=0;                    /* don't want to go negative */
        !          1258:                else
        !          1259:                        i-=headers;
        !          1260:                if(fseek(smb->sda_fp,-2L,SEEK_CUR)) {
        !          1261:                        sprintf(smb->last_error,"seeking backwards 2 bytes in allocation file");
        !          1262:                        return(3);
        !          1263:                }
        !          1264:                if(!fwrite(&i,2,1,smb->sda_fp)) {
        !          1265:                        sprintf(smb->last_error,"writing allocation bytes");
        !          1266:                        return(4)        !          1267:                }
        !          1268:        }
        !          1269:        fflush(smb->sda_fp);
        !          1270:        if(da_opened)
        !          1271:                smb_close_da(smb);
        !          1272:        return(0);
        !          1273: }
        !          1274: 
        !          1275: /****************************************************************************/
        !          1276: /* Adds to data allocation records for blocks starting at 'offset'          */
        !          1277: /* Returns non-zero on error                                                                                           */
        !          1278: /****************************************************************************/
        !          1279: int SMBCALL smb_incdat(smb_t* smb, ulong offset, ulong length, ushort headers)
        !          1280: {
        !          1281:        ushort  i;
        !          1282:        ulong   l,blocks;
        !          1283: 
        !          1284:        clearerr(smb->sda_fp);
        !          1285:        blocks=smb_datblocks(length);
        !          1286:        for(l=0;l<blocks;l++) {
        !          1287:                fseek(smb->sda_fp,((offset/SDT_BLOCK_LEN)+l)*2L,SEEK_SET);
        !          1288:                if(!fread(&i,2,1,smb->sda_fp)) {
        !          1289:                        sprintf(smb->last_error,"reading allocation record");                   
        !          1290:                        return(1);
        !          1291:                }
        !          1292:                i+=headers;
        !          1293:                fseek(smb->sda_fp,-2L,SEEK_CUR);
        !          1294:                if(!fwrite(&i,2,1,smb->sda_fp)) {
        !          1295:                        sprintf(smb->last_error,"writing allocation record");
        !          1296:                        return(2)        !          1297:                }
        !          1298:        }
        !          1299:        fflush(smb->sda_fp);
        !          1300:        return(0);
        !          1301: }
        !          1302: 
        !          1303: /****************************************************************************/
        !          1304: /* De-allocates blocks for header record                                                                       */
        !          1305: /* Returns non-zero on error                                                                                           */
        !          1306: /****************************************************************************/
        !          1307: int SMBCALL smb_freemsghdr(smb_t* smb, ulong offset, ulong length)
        !          1308: {
        !          1309:        uchar   c=0;
        !          1310:        ulong   l,blocks;
        !          1311: 
        !          1312:        clearerr(smb->sha_fp);
        !          1313:        blocks=smb_hdrblocks(length);
        !          1314:        fseek(smb->sha_fp,offset/SHD_BLOCK_LEN,SEEK_SET);
        !          1315:        for(l=0;l<blocks;l++)
        !          1316:                if(!fwrite(&c,1,1,smb->sha_fp)) {
        !          1317:                        sprintf(smb->last_error,"writing allocation record");
        !          1318:                        return(1);
        !          1319:                }
        !          1320:        fflush(smb->sha_fp);
        !          1321:        return(0);
        !          1322: }
        !          1323: 
        !          1324: /****************************************************************************/
        !          1325: /* Frees all allocated header and data blocks for 'msg'                     */
        !          1326: /****************************************************************************/
        !          1327: int SMBCALL smb_freemsg(smb_t* smb, smbmsg_t* msg)
        !          1328: {
        !          1329:        int     i;
        !          1330:        ushort  x;
        !          1331: 
        !          1332:        if(smb->status.attr&SMB_HYPERALLOC)  /* Nothing to do */
        !          1333:                return(0);
        !          1334: 
        !          1335:        for(x=0;x<msg->hdr.total_dfields;x++) {
        !          1336:                if((i=smb_freemsgdat(smb,msg->hdr.offset+msg->dfield[x].offset
        !          1337:                        ,msg->dfield[x].length,1))!=0)
        !          1338:                        return(i); 
        !          1339:        }
        !          1340:        return(smb_freemsghdr(smb,msg->idx.offset-smb->status.header_offset
        !          1341:                ,msg->hdr.length));
        !          1342: }
        !          1343: 
        !          1344: /****************************************************************************/
        !          1345: /* Finds unused space in header file based on block allocation table and       */
        !          1346: /* marks space as used in allocation table.                                 */
        !          1347: /* File must be opened read/write DENY ALL                                                                     */
        !          1348: /* Returns offset to beginning of header (in bytes, not blocks)                        */
        !          1349: /* Assumes smb_open_ha() has been called                                                                       */
        !          1350: /* smb_close_ha() should be called after                                                                       */
        !          1351: /* Returns -1L on error                                                                                                        */
        !          1352: /****************************************************************************/
        !          1353: long SMBCALL smb_allochdr(smb_t* smb, ulong length)
        !          1354: {
        !          1355:        uchar   c;
        !          1356:        ushort  i;
        !          1357:        ulong   l,blocks,offset=0;
        !          1358: 
        !          1359:        blocks=smb_hdrblocks(length);
        !          1360:        i=0;    /* i is consecutive unused block counter */
        !          1361:        fflush(smb->sha_fp);
        !          1362:        rewind(smb->sha_fp);
        !          1363:        while(!feof(smb->sha_fp)) {
        !          1364:                if(!fread(&c,1,1,smb->sha_fp)) 
        !          1365:                        break;
        !          1366:                offset+=SHD_BLOCK_LEN;
        !          1367:                if(!c) i++;
        !          1368:                else   i=0;
        !          1369:                if(i==blocks) {
        !          1370:                        offset-=(blocks*SHD_BLOCK_LEN);
        !          1371:                        break; 
        !          1372:                } 
        !          1373:        }
        !          1374:        clearerr(smb->sha_fp);
        !          1375:        fseek(smb->sha_fp,offset/SHD_BLOCK_LEN,SEEK_SET);
        !          1376:        c=1;
        !          1377:        for(l=0;l<blocks;l++)
        !          1378:                if(!fwrite(&c,1,1,smb->sha_fp)) {
        !          1379:                        sprintf(smb->last_error,"writing allocation record");
        !          1380:                        return(-1L);
        !          1381:                }
        !          1382:        fflush(smb->sha_fp);
        !          1383:        return(offset);
        !          1384: }
        !          1385: 
        !          1386: /****************************************************************************/
        !          1387: /* Allocates space for index, but doesn't search for unused blocks          */
        !          1388: /* Returns -1L on error                                                                                                        */
        !          1389: /****************************************************************************/
        !          1390: long SMBCALL smb_fallochdr(smb_t* smb, ulong length)
        !          1391: {
        !          1392:        uchar   c=1;
        !          1393:        ulong   l,blocks,offset;
        !          1394: 
        !          1395:        blocks=smb_hdrblocks(length);
        !          1396:        fflush(smb->sha_fp);
        !          1397:        clearerr(smb->sha_fp);
        !          1398:        fseek(smb->sha_fp,0L,SEEK_END);
        !          1399:        offset=ftell(smb->sha_fp)*SHD_BLOCK_LEN;
        !          1400:        for(l=0;l<blocks;l++)
        !          1401:                if(!fwrite(&c,1,1,smb->sha_fp)) {
        !          1402:                        sprintf(smb->last_error,"writing allocation record");
        !          1403:                        return(-1L);
        !          1404:                }
        !          1405:        fflush(smb->sha_fp);
        !          1406:        return(offset);
        !          1407: }
        !          1408: 
        !          1409: /************************************************************************/
        !          1410: /* Allocate header blocks using Hyper Allocation                                               */
        !          1411: /* this function should be most likely not be called from anywhere but */
        !          1412: /* smb_addmsghdr()                                                                                                             */
        !          1413: /************************************************************************/
        !          1414: long SMBCALL smb_hallochdr(smb_t* smb)
        !          1415: {
        !          1416:        ulong l;
        !          1417: 
        !          1418:        fflush(smb->shd_fp);
        !          1419:        fseek(smb->shd_fp,0L,SEEK_END);
        !          1420:        l=ftell(smb->shd_fp);
        !          1421:        if(l<smb->status.header_offset)                          /* Header file truncated?!? */
        !          1422:                return(smb->status.header_offset);
        !          1423:        while((l-smb->status.header_offset)%SHD_BLOCK_LEN)      /* Even block boundry */
        !          1424:                l++;
        !          1425:        return(l-smb->status.header_offset);
        !          1426: }
        !          1427: 
        !          1428: /************************************************************************/
        !          1429: /* Allocate data blocks using Hyper Allocation                                                 */
        !          1430: /* smb_locksmbhdr() should be called before this function and not              */
        !          1431: /* unlocked until all data fields for this message have been written   */
        !          1432: /* to the SDT file                                                                                                             */
        !          1433: /************************************************************************/
        !          1434: long SMBCALL smb_hallocdat(smb_t* smb)
        !          1435: {
        !          1436:        long l;
        !          1437: 
        !          1438:        fflush(smb->sdt_fp);
        !          1439:        fseek(smb->sdt_fp,0L,SEEK_END);
        !          1440:        l=ftell(smb->sdt_fp);
        !          1441:        if(l<=0)
        !          1442:                return(l);
        !          1443:        while(l%SDT_BLOCK_LEN)                                  /* Make sure even block boundry */
        !          1444:                l++;
        !          1445:        return(l);
        !          1446: }
        !          1447: 
        !          1448: 
        !          1449: int SMBCALL smb_feof(FILE* fp)
        !          1450: {
        !          1451:        return(feof(fp));
        !          1452: }
        !          1453: 
        !          1454: int SMBCALL smb_ferror(FILE* fp)
        !          1455: {
        !          1456:        return(ferror(fp));
        !          1457: }
        !          1458: 
        !          1459: int SMBCALL smb_fflush(FILE* fp)
        !          1460: {
        !          1461:        return(fflush(fp));
        !          1462: }
        !          1463: 
        !          1464: int SMBCALL smb_fgetc(FILE* fp)
        !          1465: {
        !          1466:        return(fgetc(fp));
        !          1467: }
        !          1468: 
        !          1469: int SMBCALL smb_fputc(int ch, FILE* fp)
        !          1470: {
        !          1471:        return(fputc(ch,fp));
        !          1472: }
        !          1473: 
        !          1474: int SMBCALL smb_fseek(FILE* fp, long offset, int whence)
        !          1475: {
        !          1476:        return(fseek(fp,offset,whence));
        !          1477: }
        !          1478: 
        !          1479: long SMBCALL smb_ftell(FILE* fp)
        !          1480: {
        !          1481:        return(ftell(fp));
        !          1482: }
        !          1483: 
        !          1484: long SMBCALL smb_fgetlength(FILE* fp)
        !          1485: {
        !          1486:        return(filelength(fileno(fp)));
        !          1487: }
        !          1488: 
        !          1489: int SMBCALL smb_fsetlength(FILE* fp, long length)
        !          1490: {
        !          1491:        return(chsize(fileno(fp),length));
        !          1492: }
        !          1493: 
        !          1494: void SMBCALL smb_rewind(FILE* fp)
        !          1495: {
        !          1496:        rewind(fp);
        !          1497: }
        !          1498: 
        !          1499: void SMBCALL smb_clearerr(FILE* fp)
        !          1500: {
        !          1501:        clearerr(fp);
        !          1502: }
        !          1503: 
        !          1504: long SMBCALL smb_fread(void HUGE16* buf, long bytes, FILE* fp)
        !          1505: {
        !          1506: #ifdef __FLAT__
        !          1507:        return(fread(buf,1,bytes,fp));
        !          1508: #else
        !          1509:        long count;
        !          1510: 
        !          1511:        for(count=bytes;count>0x7fff;count-=0x7fff,(char*)buf+=0x7fff)
        !          1512:                if(fread((char*)buf,1,0x7fff,fp)!=0x7fff)
        !          1513:                        return(bytes-count);
        !          1514:        if(fread((char*)buf,1,(size_t)count,fp)!=(size_t)count)
        !          1515:                return(bytes-count);
        !          1516:        return(bytes);
        !          1517: #endif
        !          1518: }
        !          1519: 
        !          1520: long SMBCALL smb_fwrite(void HUGE16* buf, long bytes, FILE* fp)
        !          1521: {
        !          1522: #ifdef __FLAT__
        !          1523:        return(fwrite(buf,1,bytes,fp));
        !          1524: #else
        !          1525:        long count;
        !          1526: 
        !          1527:        for(count=bytes;count>0x7fff;count-=0x7fff,(char*)buf+=0x7fff)
        !          1528:                if(fwrite((char*)buf,1,0x7fff,fp)!=0x7fff)
        !          1529:                        return(bytes-count);
        !          1530:        if(fwrite((char*)buf,1,(size_t)count,fp)!=(size_t)count)
        !          1531:                return(bytes-count);
        !          1532:        return(bytes);
        !          1533: #endif
        !          1534: }
        !          1535: 
        !          1536: /* End of SMBLIB.C */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.