Annotation of sbbs/sbbs3/smblib.c, revision 1.1.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.