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

1.1     ! root        1: /* smblib.c */
        !             2: 
        !             3: /* Synchronet message base (SMB) library routines */
        !             4: 
        !             5: /* $Id: smblib.c,v 1.127 2004/12/31 09:38:52 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 2004 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: /* ANSI C Library headers */
        !            39: 
        !            40: #include <time.h>
        !            41: #include <errno.h>
        !            42: #include <fcntl.h>
        !            43: #include <stdio.h>
        !            44: #include <stdlib.h>            /* malloc */
        !            45: #include <string.h>
        !            46: #include <ctype.h>             /* isdigit */
        !            47: #include <sys/types.h>
        !            48: #include <sys/stat.h>  /* must come after sys/types.h */
        !            49: 
        !            50: /* SMB-specific headers */
        !            51: #include "smblib.h"
        !            52: #include "genwrap.h"
        !            53: #include "filewrap.h"
        !            54: 
        !            55: /* Use smb_ver() and smb_lib_ver() to obtain these values */
        !            56: #define SMBLIB_VERSION         "2.40"      /* SMB library version */
        !            57: #define SMB_VERSION            0x0121          /* SMB format version */
        !            58:                                                                                /* High byte major, low byte minor */
        !            59: 
        !            60: static char* nulstr="";
        !            61: 
        !            62: int SMBCALL smb_ver(void)
        !            63: {
        !            64:        return(SMB_VERSION);
        !            65: }
        !            66: 
        !            67: char* SMBCALL smb_lib_ver(void)
        !            68: {
        !            69:        return(SMBLIB_VERSION);
        !            70: }
        !            71: 
        !            72: /****************************************************************************/
        !            73: /* Open a message base of name 'smb->file'                                  */
        !            74: /* Opens files for READing messages or updating message indices only        */
        !            75: /****************************************************************************/
        !            76: int SMBCALL smb_open(smb_t* smb)
        !            77: {
        !            78:        int                     i;
        !            79:        time_t          start=0;
        !            80:        smbhdr_t        hdr;
        !            81: 
        !            82:        /* Set default values, if uninitialized */
        !            83:        if(!smb->retry_time)
        !            84:                smb->retry_time=10;             /* seconds */
        !            85:        if(!smb->retry_delay 
        !            86:                || smb->retry_delay>(smb->retry_time*100))      /* at least ten retries */
        !            87:                smb->retry_delay=250;   /* milliseconds */
        !            88:        smb->shd_fp=smb->sdt_fp=smb->sid_fp=NULL;
        !            89:        smb->sha_fp=smb->sda_fp=smb->hash_fp=NULL;
        !            90:        smb->last_error[0]=0;
        !            91: 
        !            92:        /* Check for message-base lock semaphore file (under maintenance?) */
        !            93:        while(smb_islocked(smb)) {
        !            94:                if(!start)
        !            95:                        start=time(NULL);
        !            96:                else
        !            97:                        if(time(NULL)-start>=(time_t)smb->retry_time)
        !            98:                                return(SMB_ERR_TIMEOUT); 
        !            99:                SLEEP(smb->retry_delay);
        !           100:        }
        !           101: 
        !           102:        if((i=smb_open_fp(smb,&smb->shd_fp,SH_DENYNO))!=SMB_SUCCESS)
        !           103:                return(i);
        !           104: 
        !           105:        memset(&(smb->status),0,sizeof(smb->status));
        !           106:        if(filelength(fileno(smb->shd_fp))>=(long)sizeof(smbhdr_t)) {
        !           107:                setvbuf(smb->shd_fp,NULL,_IONBF,SHD_BLOCK_LEN);
        !           108:                if(smb_locksmbhdr(smb)!=SMB_SUCCESS) {
        !           109:                        smb_close(smb);
        !           110:                        /* smb_lockmsghdr set last_error */
        !           111:                        return(SMB_ERR_LOCK); 
        !           112:                }
        !           113:                memset(&hdr,0,sizeof(smbhdr_t));
        !           114:                if(smb_fread(smb,&hdr,sizeof(smbhdr_t),smb->shd_fp)!=sizeof(smbhdr_t)) {
        !           115:                        safe_snprintf(smb->last_error,sizeof(smb->last_error)
        !           116:                                ,"%d '%s' reading header"
        !           117:                                ,get_errno(),STRERROR(get_errno()));
        !           118:                        smb_close(smb);
        !           119:                        return(SMB_ERR_READ);
        !           120:                }
        !           121:                if(memcmp(hdr.id,SMB_HEADER_ID,LEN_HEADER_ID)) {
        !           122:                        safe_snprintf(smb->last_error,sizeof(smb->last_error)
        !           123:                                ,"corrupt SMB header ID: %.*s"
        !           124:                                ,LEN_HEADER_ID,hdr.id);
        !           125:                        smb_close(smb);
        !           126:                        return(SMB_ERR_HDR_ID); 
        !           127:                }
        !           128:                if(hdr.version<0x110) {         /* Compatibility check */
        !           129:                        safe_snprintf(smb->last_error,sizeof(smb->last_error)
        !           130:                                ,"insufficient header version: %X"
        !           131:                                ,hdr.version);
        !           132:                        smb_close(smb);
        !           133:                        return(SMB_ERR_HDR_VER); 
        !           134:                }
        !           135:                if(smb_fread(smb,&(smb->status),sizeof(smbstatus_t),smb->shd_fp)!=sizeof(smbstatus_t)) {
        !           136:                        safe_snprintf(smb->last_error,sizeof(smb->last_error)
        !           137:                                ,"%d '%s' reading status"
        !           138:                                ,get_errno(),STRERROR(get_errno()));
        !           139:                        smb_close(smb);
        !           140:                        return(SMB_ERR_READ); 
        !           141:                }
        !           142:                if((i=smb_unlocksmbhdr(smb))!=SMB_SUCCESS) {
        !           143:                        smb_close(smb);
        !           144:                        return(i);
        !           145:                }
        !           146:                rewind(smb->shd_fp); 
        !           147:        }
        !           148: 
        !           149:        setvbuf(smb->shd_fp,NULL,_IOFBF,SHD_BLOCK_LEN);
        !           150: 
        !           151:        if((i=smb_open_fp(smb,&smb->sdt_fp,SH_DENYNO))!=SMB_SUCCESS)
        !           152:                return(i);
        !           153: 
        !           154:        if((i=smb_open_fp(smb,&smb->sid_fp,SH_DENYNO))!=SMB_SUCCESS)
        !           155:                return(i);
        !           156: 
        !           157:        return(SMB_SUCCESS);
        !           158: }
        !           159: 
        !           160: /****************************************************************************/
        !           161: /* Closes the currently open message base                                                                      */
        !           162: /****************************************************************************/
        !           163: void SMBCALL smb_close(smb_t* smb)
        !           164: {
        !           165:        if(smb->shd_fp!=NULL) {
        !           166:                smb_unlocksmbhdr(smb);             /* In case it's been locked */
        !           167:                smb_close_fp(&smb->shd_fp); 
        !           168:        }
        !           169:        smb_close_fp(&smb->sdt_fp);
        !           170:        smb_close_fp(&smb->sid_fp);
        !           171:        smb_close_fp(&smb->sda_fp);
        !           172:        smb_close_fp(&smb->sha_fp);
        !           173:        smb_close_fp(&smb->hash_fp);
        !           174: }
        !           175: 
        !           176: /****************************************************************************/
        !           177: /* This set of functions is used to exclusively-lock an entire message base    */
        !           178: /* against any other process opening any of the message base files.                    */
        !           179: /* Currently, this is only used while smbutil packs a message base.                    */
        !           180: /* This is achieved with a semaphore lock file (e.g. mail.lock).                       */
        !           181: /****************************************************************************/
        !           182: static char* smb_lockfname(smb_t* smb, char* fname, size_t maxlen)
        !           183: {
        !           184:        safe_snprintf(fname,maxlen,"%s.lock",smb->file);
        !           185:        return(fname);
        !           186: }
        !           187: 
        !           188: /****************************************************************************/
        !           189: /* This function is used to lock an entire message base for exclusive          */
        !           190: /* (typically for maintenance/repair)                                                                          */
        !           191: /****************************************************************************/
        !           192: int SMBCALL smb_lock(smb_t* smb)
        !           193: {
        !           194:        char    path[MAX_PATH+1];
        !           195:        int             file;
        !           196:        time_t  start=0;
        !           197: 
        !           198:        smb_lockfname(smb,path,sizeof(path)-1);
        !           199:        while((file=open(path,O_CREAT|O_EXCL|O_RDWR,S_IREAD|S_IWRITE))==-1) {
        !           200:                if(!start)
        !           201:                        start=time(NULL);
        !           202:                else
        !           203:                        if(time(NULL)-start>=(time_t)smb->retry_time) {
        !           204:                                safe_snprintf(smb->last_error,sizeof(smb->last_error)
        !           205:                                        ,"%d '%s' creating %s"
        !           206:                                        ,get_errno(),STRERROR(get_errno()),path);
        !           207:                                return(SMB_ERR_LOCK);
        !           208:                        }
        !           209:                SLEEP(smb->retry_delay);
        !           210:        }
        !           211:        close(file);
        !           212:        return(SMB_SUCCESS);
        !           213: }
        !           214: 
        !           215: int SMBCALL smb_unlock(smb_t* smb)
        !           216: {
        !           217:        char    path[MAX_PATH+1];
        !           218: 
        !           219:        smb_lockfname(smb,path,sizeof(path)-1);
        !           220:        if(remove(path)!=0) {
        !           221:                safe_snprintf(smb->last_error,sizeof(smb->last_error)
        !           222:                        ,"%d '%s' removing %s"
        !           223:                        ,get_errno(),STRERROR(get_errno()),path);
        !           224:                return(SMB_ERR_DELETE);
        !           225:        }
        !           226:        return(SMB_SUCCESS);
        !           227: }
        !           228: 
        !           229: BOOL SMBCALL smb_islocked(smb_t* smb)
        !           230: {
        !           231:        char    path[MAX_PATH+1];
        !           232: 
        !           233:        if(access(smb_lockfname(smb,path,sizeof(path)-1),0)!=0)
        !           234:                return(FALSE);
        !           235:        safe_snprintf(smb->last_error,sizeof(smb->last_error),"%s exists",path);
        !           236:        return(TRUE);
        !           237: }
        !           238: 
        !           239: /****************************************************************************/
        !           240: /* If the parameter 'push' is non-zero, this function stores the currently  */
        !           241: /* open message base to the "virtual" smb stack. Up to SMB_STACK_LEN        */
        !           242: /* message bases may be stored (defined in SMBDEFS.H).                                         */
        !           243: /* The parameter 'op' is the operation to perform on the stack. Either      */
        !           244: /* SMB_STACK_PUSH, SMB_STACK_POP, or SMB_STACK_XCHNG                                           */
        !           245: /* If the operation is SMB_STACK_POP, this function restores a message base */
        !           246: /* previously saved with a SMB_STACK_PUSH call to this same function.          */
        !           247: /* If the operation is SMB_STACK_XCHNG, then the current message base is       */
        !           248: /* exchanged with the message base on the top of the stack (most recently      */
        !           249: /* pushed.                                                                                                                                     */
        !           250: /* If the current message base is not open, the SMB_STACK_PUSH and                     */
        !           251: /* SMB_STACK_XCHNG operations do nothing                                                                       */
        !           252: /* Returns 0 on success, non-zero if stack full.                            */
        !           253: /* If operation is SMB_STACK_POP or SMB_STACK_XCHNG, it always returns 0.      */
        !           254: /****************************************************************************/
        !           255: int SMBCALL smb_stack(smb_t* smb, int op)
        !           256: {
        !           257:        static smb_t stack[SMB_STACK_LEN];
        !           258:        static int      stack_idx;
        !           259:        smb_t           tmp_smb;
        !           260: 
        !           261:        if(op==SMB_STACK_PUSH) {
        !           262:                if(stack_idx>=SMB_STACK_LEN) {
        !           263:                        safe_snprintf(smb->last_error,sizeof(smb->last_error),"SMB stack overflow");
        !           264:                        return(SMB_FAILURE);
        !           265:                }
        !           266:                if(smb->shd_fp==NULL || smb->sdt_fp==NULL || smb->sid_fp==NULL)
        !           267:                        return(SMB_SUCCESS);      /* Msg base not open, do nothing */
        !           268:                memcpy(&stack[stack_idx],smb,sizeof(smb_t));
        !           269:                stack_idx++;
        !           270:                return(SMB_SUCCESS); 
        !           271:        }
        !           272:        /* pop or xchng */
        !           273:        if(!stack_idx)  /* Nothing on the stack, so do nothing */
        !           274:                return(SMB_SUCCESS);
        !           275:        if(op==SMB_STACK_XCHNG) {
        !           276:                if(smb->shd_fp==NULL)
        !           277:                        return(SMB_SUCCESS);
        !           278:                memcpy(&tmp_smb,smb,sizeof(smb_t));
        !           279:        }
        !           280: 
        !           281:        stack_idx--;
        !           282:        memcpy(smb,&stack[stack_idx],sizeof(smb_t));
        !           283:        if(op==SMB_STACK_XCHNG) {
        !           284:                memcpy(&stack[stack_idx],&tmp_smb,sizeof(smb_t));
        !           285:                stack_idx++;
        !           286:        }
        !           287:        return(SMB_SUCCESS);
        !           288: }
        !           289: 
        !           290: /****************************************************************************/
        !           291: /* Truncates header file                                                                                                       */
        !           292: /* Retrys for smb.retry_time number of seconds                                                         */
        !           293: /* Return 0 on success, non-zero otherwise                                                                     */
        !           294: /****************************************************************************/
        !           295: int SMBCALL smb_trunchdr(smb_t* smb)
        !           296: {
        !           297:        time_t  start=0;
        !           298: 
        !           299:        if(smb->shd_fp==NULL) {
        !           300:                safe_snprintf(smb->last_error,sizeof(smb->last_error),"msgbase not open");
        !           301:                return(SMB_ERR_NOT_OPEN);
        !           302:        }
        !           303:        rewind(smb->shd_fp);
        !           304:        while(1) {
        !           305:                if(chsize(fileno(smb->shd_fp),0L)==0)
        !           306:                        break;
        !           307:                if(get_errno()!=EACCES && get_errno()!=EAGAIN) {
        !           308:                        safe_snprintf(smb->last_error,sizeof(smb->last_error)
        !           309:                                ,"%d '%s' changing header file size"
        !           310:                                ,get_errno(),STRERROR(get_errno()));
        !           311:                        return(SMB_ERR_WRITE);
        !           312:                }
        !           313:                if(!start)
        !           314:                        start=time(NULL);
        !           315:                else
        !           316:                        if(time(NULL)-start>=(time_t)smb->retry_time) {  /* Time-out */
        !           317:                                safe_snprintf(smb->last_error,sizeof(smb->last_error)
        !           318:                                        ,"timeout changing header file size (retry_time=%ld)"
        !           319:                                        ,smb->retry_time);
        !           320:                                return(SMB_ERR_TIMEOUT); 
        !           321:                        }
        !           322:                SLEEP(smb->retry_delay);
        !           323:        }
        !           324:        return(SMB_SUCCESS);
        !           325: }
        !           326: 
        !           327: /*********************************/
        !           328: /* Message Base Header Functions */
        !           329: /*********************************/
        !           330: 
        !           331: /****************************************************************************/
        !           332: /* Attempts for smb.retry_time number of seconds to lock the msg base hdr      */
        !           333: /****************************************************************************/
        !           334: int SMBCALL smb_locksmbhdr(smb_t* smb)
        !           335: {
        !           336:        time_t  start=0;
        !           337: 
        !           338:        if(smb->shd_fp==NULL) {
        !           339:                safe_snprintf(smb->last_error,sizeof(smb->last_error),"msgbase not open");
        !           340:                return(SMB_ERR_NOT_OPEN);
        !           341:        }
        !           342:        while(1) {
        !           343:                if(lock(fileno(smb->shd_fp),0L,sizeof(smbhdr_t)+sizeof(smbstatus_t))==0) {
        !           344:                        smb->locked=TRUE;
        !           345:                        return(SMB_SUCCESS);
        !           346:                }
        !           347:                if(!start)
        !           348:                        start=time(NULL);
        !           349:                else
        !           350:                        if(time(NULL)-start>=(time_t)smb->retry_time) 
        !           351:                                break;                                          
        !           352:                /* In case we've already locked it */
        !           353:                if(unlock(fileno(smb->shd_fp),0L,sizeof(smbhdr_t)+sizeof(smbstatus_t))==0)
        !           354:                        smb->locked=FALSE;
        !           355:                else {
        !           356:                        SLEEP(smb->retry_delay);
        !           357:                }
        !           358:        }
        !           359:        safe_snprintf(smb->last_error,sizeof(smb->last_error),"timeout locking header");
        !           360:        return(SMB_ERR_TIMEOUT);
        !           361: }
        !           362: 
        !           363: /****************************************************************************/
        !           364: /* Read the SMB header from the header file and place into smb.status          */
        !           365: /****************************************************************************/
        !           366: int SMBCALL smb_getstatus(smb_t* smb)
        !           367: {
        !           368:        int     i;
        !           369: 
        !           370:        if(smb->shd_fp==NULL) {
        !           371:                safe_snprintf(smb->last_error,sizeof(smb->last_error),"msgbase not open");
        !           372:                return(SMB_ERR_NOT_OPEN);
        !           373:        }
        !           374:        setvbuf(smb->shd_fp,NULL,_IONBF,SHD_BLOCK_LEN);
        !           375:        clearerr(smb->shd_fp);
        !           376:        if(fseek(smb->shd_fp,sizeof(smbhdr_t),SEEK_SET)) {
        !           377:                safe_snprintf(smb->last_error,sizeof(smb->last_error)
        !           378:                        ,"%d '%s' seeking to %u in header file"
        !           379:                        ,get_errno(),STRERROR(get_errno()),sizeof(smbhdr_t));
        !           380:                return(SMB_ERR_SEEK);
        !           381:        }
        !           382:        i=smb_fread(smb,&(smb->status),sizeof(smbstatus_t),smb->shd_fp);
        !           383:        setvbuf(smb->shd_fp,NULL,_IOFBF,SHD_BLOCK_LEN);
        !           384:        if(i==sizeof(smbstatus_t))
        !           385:                return(SMB_SUCCESS);
        !           386:        safe_snprintf(smb->last_error,sizeof(smb->last_error)
        !           387:                ,"%d '%s' reading status",get_errno(),STRERROR(get_errno()));
        !           388:        return(SMB_ERR_READ);
        !           389: }
        !           390: 
        !           391: /****************************************************************************/
        !           392: /* Writes message base header                                                                                          */
        !           393: /****************************************************************************/
        !           394: int SMBCALL smb_putstatus(smb_t* smb)
        !           395: {
        !           396:        int i;
        !           397: 
        !           398:        if(smb->shd_fp==NULL) {
        !           399:                safe_snprintf(smb->last_error,sizeof(smb->last_error),"msgbase not open");
        !           400:                return(SMB_ERR_NOT_OPEN);
        !           401:        }
        !           402:        clearerr(smb->shd_fp);
        !           403:        if(fseek(smb->shd_fp,sizeof(smbhdr_t),SEEK_SET)) {
        !           404:                safe_snprintf(smb->last_error,sizeof(smb->last_error)
        !           405:                        ,"%d '%s' seeking to %u in header file"
        !           406:                        ,get_errno(),STRERROR(get_errno()),sizeof(smbhdr_t));
        !           407:                return(SMB_ERR_SEEK);
        !           408:        }
        !           409:        i=fwrite(&(smb->status),1,sizeof(smbstatus_t),smb->shd_fp);
        !           410:        fflush(smb->shd_fp);
        !           411:        if(i==sizeof(smbstatus_t))
        !           412:                return(SMB_SUCCESS);
        !           413:        safe_snprintf(smb->last_error,sizeof(smb->last_error)
        !           414:                ,"%d '%s' writing status",get_errno(),STRERROR(get_errno()));
        !           415:        return(SMB_ERR_WRITE);
        !           416: }
        !           417: 
        !           418: /****************************************************************************/
        !           419: /* Unlocks previously locked message base header                                                       */
        !           420: /****************************************************************************/
        !           421: int SMBCALL smb_unlocksmbhdr(smb_t* smb)
        !           422: {
        !           423:        if(smb->locked) {
        !           424:                if(smb->shd_fp==NULL) {
        !           425:                        safe_snprintf(smb->last_error,sizeof(smb->last_error),"msgbase not open");
        !           426:                        return(SMB_ERR_NOT_OPEN);
        !           427:                }
        !           428:                if(unlock(fileno(smb->shd_fp),0L,sizeof(smbhdr_t)+sizeof(smbstatus_t))!=0) {
        !           429:                        safe_snprintf(smb->last_error,sizeof(smb->last_error)
        !           430:                                ,"%d '%s' unlocking message base header",get_errno(),STRERROR(get_errno()));
        !           431:                        return(SMB_ERR_UNLOCK);
        !           432:                }
        !           433:                smb->locked=FALSE;
        !           434:        }
        !           435:        return(SMB_SUCCESS);
        !           436: }
        !           437: 
        !           438: /********************************/
        !           439: /* Individual Message Functions */
        !           440: /********************************/
        !           441: 
        !           442: /****************************************************************************/
        !           443: /* Is the offset a valid message header offset?                                                                */
        !           444: /****************************************************************************/
        !           445: BOOL SMBCALL smb_valid_hdr_offset(smb_t* smb, ulong offset)
        !           446: {
        !           447:        if(offset<sizeof(smbhdr_t)+sizeof(smbstatus_t) 
        !           448:                || offset<smb->status.header_offset) {
        !           449:                safe_snprintf(smb->last_error,sizeof(smb->last_error)
        !           450:                        ,"invalid header offset: %lu (0x%lX)"
        !           451:                        ,offset,offset);
        !           452:                return(FALSE);
        !           453:        }
        !           454:        return(TRUE);
        !           455: }
        !           456: 
        !           457: /****************************************************************************/
        !           458: /* Attempts for smb.retry_time number of seconds to lock the hdr for 'msg'  */
        !           459: /****************************************************************************/
        !           460: int SMBCALL smb_lockmsghdr(smb_t* smb, smbmsg_t* msg)
        !           461: {
        !           462:        time_t  start=0;
        !           463: 
        !           464:        if(smb->shd_fp==NULL) {
        !           465:                safe_snprintf(smb->last_error,sizeof(smb->last_error),"msgbase not open");
        !           466:                return(SMB_ERR_NOT_OPEN);
        !           467:        }
        !           468:        if(!smb_valid_hdr_offset(smb,msg->idx.offset))
        !           469:                return(SMB_ERR_HDR_OFFSET);
        !           470: 
        !           471:        while(1) {
        !           472:                if(lock(fileno(smb->shd_fp),msg->idx.offset,sizeof(msghdr_t))==0)
        !           473:                        return(SMB_SUCCESS);
        !           474:                if(!start)
        !           475:                        start=time(NULL);
        !           476:                else
        !           477:                        if(time(NULL)-start>=(time_t)smb->retry_time) 
        !           478:                                break;
        !           479:                /* In case we've already locked it */
        !           480:                if(unlock(fileno(smb->shd_fp),msg->idx.offset,sizeof(msghdr_t))!=0) {
        !           481:                        SLEEP(smb->retry_delay);
        !           482:                }
        !           483:        }
        !           484:        safe_snprintf(smb->last_error,sizeof(smb->last_error),"timeout locking header");
        !           485:        return(SMB_ERR_TIMEOUT);
        !           486: }
        !           487: 
        !           488: /****************************************************************************/
        !           489: /* Fills msg->idx with message index based on msg->hdr.number                          */
        !           490: /* OR if msg->hdr.number is 0, based on msg->offset (record offset).           */
        !           491: /* if msg.hdr.number does not equal 0, then msg->offset is filled too.         */
        !           492: /* Either msg->hdr.number or msg->offset must be initialized before            */
        !           493: /* calling this function                                                                                                       */
        !           494: /* Returns 1 if message number wasn't found, 0 if it was                    */
        !           495: /****************************************************************************/
        !           496: int SMBCALL smb_getmsgidx(smb_t* smb, smbmsg_t* msg)
        !           497: {
        !           498:        idxrec_t        idx;
        !           499:        ulong           byte_offset;
        !           500:        ulong           l,length,total,bot,top;
        !           501: 
        !           502:        if(smb->sid_fp==NULL) {
        !           503:                safe_snprintf(smb->last_error,sizeof(smb->last_error),"index not open");
        !           504:                return(SMB_ERR_NOT_OPEN);
        !           505:        }
        !           506:        clearerr(smb->sid_fp);
        !           507: 
        !           508:        length=filelength(fileno(smb->sid_fp));
        !           509:        if(length<sizeof(idxrec_t)) {
        !           510:                safe_snprintf(smb->last_error,sizeof(smb->last_error)
        !           511:                        ,"invalid index file length: %ld",length);
        !           512:                return(SMB_ERR_FILE_LEN);
        !           513:        }
        !           514:        total=length/sizeof(idxrec_t);
        !           515:        if(!total) {
        !           516:                safe_snprintf(smb->last_error,sizeof(smb->last_error)
        !           517:                        ,"invalid index file length: %ld",length);
        !           518:                return(SMB_ERR_FILE_LEN);
        !           519:        }
        !           520: 
        !           521:        if(!msg->hdr.number) {
        !           522:                if(msg->offset<0)
        !           523:                        byte_offset=length-((-msg->offset)*sizeof(idxrec_t));
        !           524:                else
        !           525:                        byte_offset=msg->offset*sizeof(idxrec_t);
        !           526:                if(byte_offset>=length) {
        !           527:                        safe_snprintf(smb->last_error,sizeof(smb->last_error)
        !           528:                                ,"invalid index offset: %ld, byte offset: %lu, length: %lu"
        !           529:                                ,msg->offset, byte_offset, length);
        !           530:                        return(SMB_ERR_HDR_OFFSET);
        !           531:                }
        !           532:                if(fseek(smb->sid_fp,byte_offset,SEEK_SET)) {
        !           533:                        safe_snprintf(smb->last_error,sizeof(smb->last_error)
        !           534:                                ,"%d '%s' seeking to offset %ld (byte %lu) in index file"
        !           535:                                ,get_errno(),STRERROR(get_errno())
        !           536:                                ,msg->offset,byte_offset);
        !           537:                        return(SMB_ERR_SEEK);
        !           538:                }
        !           539:                if(smb_fread(smb,&msg->idx,sizeof(idxrec_t),smb->sid_fp)!=sizeof(idxrec_t)) {
        !           540:                        safe_snprintf(smb->last_error,sizeof(smb->last_error)
        !           541:                                ,"%d '%s' reading index at offset %ld (byte %lu)"
        !           542:                                ,get_errno(),STRERROR(get_errno())
        !           543:                                ,msg->offset,byte_offset);
        !           544:                        return(SMB_ERR_READ);
        !           545:                }
        !           546:                return(SMB_SUCCESS); 
        !           547:        }
        !           548: 
        !           549:        bot=0;
        !           550:        top=total;
        !           551:        l=total/2; /* Start at middle index */
        !           552:        while(1) {
        !           553:                if(l>=total) {
        !           554:                        safe_snprintf(smb->last_error,sizeof(smb->last_error),"msg %lu not found"
        !           555:                                ,msg->hdr.number);
        !           556:                        return(SMB_ERR_NOT_FOUND);
        !           557:                }
        !           558:                if(fseek(smb->sid_fp,l*sizeof(idxrec_t),SEEK_SET)) {
        !           559:                        safe_snprintf(smb->last_error,sizeof(smb->last_error)
        !           560:                                ,"%d '%s' seeking to offset %lu (byte %lu) in index file"
        !           561:                                ,get_errno(),STRERROR(get_errno())
        !           562:                                ,l,l*sizeof(idxrec_t));
        !           563:                        return(SMB_ERR_SEEK);
        !           564:                }
        !           565:                if(smb_fread(smb,&idx,sizeof(idxrec_t),smb->sid_fp)!=sizeof(idxrec_t)) {
        !           566:                        safe_snprintf(smb->last_error,sizeof(smb->last_error)
        !           567:                                ,"%d '%s' reading index at offset %lu (byte %lu)"
        !           568:                                ,get_errno(),STRERROR(get_errno()),l,l*sizeof(idxrec_t));
        !           569:                        return(SMB_ERR_READ);
        !           570:                }
        !           571:                if(bot==top-1 && idx.number!=msg->hdr.number) {
        !           572:                        safe_snprintf(smb->last_error,sizeof(smb->last_error),"msg %lu not found"
        !           573:                                ,msg->hdr.number);
        !           574:                        return(SMB_ERR_NOT_FOUND);
        !           575:                }
        !           576:                if(idx.number>msg->hdr.number) {
        !           577:                        top=l;
        !           578:                        l=bot+((top-bot)/2);
        !           579:                        continue; 
        !           580:                }
        !           581:                if(idx.number<msg->hdr.number) {
        !           582:                        bot=l;
        !           583:                        l=top-((top-bot)/2);
        !           584:                        continue; 
        !           585:                }
        !           586:                break; 
        !           587:        }
        !           588:        msg->idx=idx;
        !           589:        msg->offset=l;
        !           590:        return(SMB_SUCCESS);
        !           591: }
        !           592: 
        !           593: /****************************************************************************/
        !           594: /* Reads the first index record in the open message base                                       */
        !           595: /****************************************************************************/
        !           596: int SMBCALL smb_getfirstidx(smb_t* smb, idxrec_t *idx)
        !           597: {
        !           598:        if(smb->sid_fp==NULL) {
        !           599:                safe_snprintf(smb->last_error,sizeof(smb->last_error),"index not open");
        !           600:                return(SMB_ERR_NOT_OPEN);
        !           601:        }
        !           602:        clearerr(smb->sid_fp);
        !           603:        if(fseek(smb->sid_fp,0,SEEK_SET)) {
        !           604:                safe_snprintf(smb->last_error,sizeof(smb->last_error)
        !           605:                        ,"%d '%s' seeking to beginning of index file"
        !           606:                        ,get_errno(),STRERROR(get_errno()));
        !           607:                return(SMB_ERR_SEEK);
        !           608:        }
        !           609:        if(smb_fread(smb,idx,sizeof(idxrec_t),smb->sid_fp)!=sizeof(idxrec_t)) {
        !           610:                safe_snprintf(smb->last_error,sizeof(smb->last_error)
        !           611:                        ,"%d '%s' reading first index"
        !           612:                        ,get_errno(),STRERROR(get_errno()));
        !           613:                return(SMB_ERR_READ);
        !           614:        }
        !           615:        return(SMB_SUCCESS);
        !           616: }
        !           617: 
        !           618: /****************************************************************************/
        !           619: /* Reads the last index record in the open message base                                        */
        !           620: /****************************************************************************/
        !           621: int SMBCALL smb_getlastidx(smb_t* smb, idxrec_t *idx)
        !           622: {
        !           623:        long length;
        !           624: 
        !           625:        if(smb->sid_fp==NULL) {
        !           626:                safe_snprintf(smb->last_error,sizeof(smb->last_error),"index not open");
        !           627:                return(SMB_ERR_NOT_OPEN);
        !           628:        }
        !           629:        clearerr(smb->sid_fp);
        !           630:        length=filelength(fileno(smb->sid_fp));
        !           631:        if(length<(long)sizeof(idxrec_t)) {
        !           632:                safe_snprintf(smb->last_error,sizeof(smb->last_error)
        !           633:                        ,"invalid index file length: %ld",length);
        !           634:                return(SMB_ERR_FILE_LEN);
        !           635:        }
        !           636:        if(fseek(smb->sid_fp,length-sizeof(idxrec_t),SEEK_SET)) {
        !           637:                safe_snprintf(smb->last_error,sizeof(smb->last_error)
        !           638:                        ,"%d '%s' seeking to %u in index file"
        !           639:                        ,get_errno(),STRERROR(get_errno())
        !           640:                        ,(unsigned)(length-sizeof(idxrec_t)));
        !           641:                return(SMB_ERR_SEEK);
        !           642:        }
        !           643:        if(smb_fread(smb,idx,sizeof(idxrec_t),smb->sid_fp)!=sizeof(idxrec_t)) {
        !           644:                safe_snprintf(smb->last_error,sizeof(smb->last_error)
        !           645:                        ,"%d '%s' reading last index"
        !           646:                        ,get_errno(),STRERROR(get_errno()));
        !           647:                return(SMB_ERR_READ);
        !           648:        }
        !           649:        return(SMB_SUCCESS);
        !           650: }
        !           651: 
        !           652: /****************************************************************************/
        !           653: /* Figures out the total length of the header record for 'msg'              */
        !           654: /* Returns length                                                                                                                      */
        !           655: /****************************************************************************/
        !           656: ulong SMBCALL smb_getmsghdrlen(smbmsg_t* msg)
        !           657: {
        !           658:        int i;
        !           659:        ulong length;
        !           660: 
        !           661:        /* fixed portion */
        !           662:        length=sizeof(msghdr_t);
        !           663:        /* data fields */
        !           664:        length+=msg->hdr.total_dfields*sizeof(dfield_t);
        !           665:        /* header fields */
        !           666:        for(i=0;i<msg->total_hfields;i++) {
        !           667:                length+=sizeof(hfield_t);
        !           668:                length+=msg->hfield[i].length; 
        !           669:        }
        !           670:        return(length);
        !           671: }
        !           672: 
        !           673: /****************************************************************************/
        !           674: /* Figures out the total length of the data buffer for 'msg'                */
        !           675: /* Returns length                                                                                                                      */
        !           676: /****************************************************************************/
        !           677: ulong SMBCALL smb_getmsgdatlen(smbmsg_t* msg)
        !           678: {
        !           679:        int i;
        !           680:        ulong length=0L;
        !           681: 
        !           682:        for(i=0;i<msg->hdr.total_dfields;i++)
        !           683:                length+=msg->dfield[i].length;
        !           684:        return(length);
        !           685: }
        !           686: 
        !           687: /****************************************************************************/
        !           688: /* Figures out the total length of the text buffer for 'msg'                */
        !           689: /* Returns length                                                                                                                      */
        !           690: /****************************************************************************/
        !           691: ulong SMBCALL smb_getmsgtxtlen(smbmsg_t* msg)
        !           692: {
        !           693:        int i;
        !           694:        ulong length=0L;
        !           695: 
        !           696:        for(i=0;i<msg->total_hfields;i++)
        !           697:                if(msg->hfield[i].type==SMB_COMMENT || msg->hfield[i].type==SMTPSYSMSG)
        !           698:                        length+=msg->hfield[i].length+2;
        !           699:        for(i=0;i<msg->hdr.total_dfields;i++)
        !           700:                if(msg->dfield[i].type==TEXT_BODY || msg->dfield[i].type==TEXT_TAIL)
        !           701:                        length+=msg->dfield[i].length;
        !           702:        return(length);
        !           703: }
        !           704: 
        !           705: static void set_convenience_ptr(smbmsg_t* msg, ushort hfield_type, void* hfield_dat)
        !           706: {
        !           707:        switch(hfield_type) {   /* convenience variables */
        !           708:                case SENDER:
        !           709:                        if(!msg->from) {
        !           710:                                msg->from=(char*)hfield_dat;
        !           711:                                break; 
        !           712:                        }
        !           713:                case FORWARDED:         /* fall through */
        !           714:                        msg->forwarded=TRUE;
        !           715:                        break;
        !           716:                case SENDERAGENT:
        !           717:                        if(!msg->forwarded)
        !           718:                                msg->from_agent=*(ushort *)hfield_dat;
        !           719:                        break;
        !           720:                case SENDEREXT:
        !           721:                        if(!msg->forwarded)
        !           722:                                msg->from_ext=(char*)hfield_dat;
        !           723:                        break;
        !           724:                case SENDERORG:
        !           725:                        if(!msg->forwarded)
        !           726:                                msg->from_org=(char*)hfield_dat;
        !           727:                        break;
        !           728:                case SENDERNETTYPE:
        !           729:                        if(!msg->forwarded)
        !           730:                                msg->from_net.type=*(ushort *)hfield_dat;
        !           731:                        break;
        !           732:                case SENDERNETADDR:
        !           733:                        if(!msg->forwarded)
        !           734:                                msg->from_net.addr=(char*)hfield_dat;
        !           735:                        break;
        !           736:                case REPLYTO:
        !           737:                        msg->replyto=(char*)hfield_dat;
        !           738:                        break;
        !           739:                case REPLYTOEXT:
        !           740:                        msg->replyto_ext=(char*)hfield_dat;
        !           741:                        break;
        !           742:                case REPLYTOAGENT:
        !           743:                        msg->replyto_agent=*(ushort *)hfield_dat;
        !           744:                        break;
        !           745:                case REPLYTONETTYPE:
        !           746:                        msg->replyto_net.type=*(ushort *)hfield_dat;
        !           747:                        break;
        !           748:                case REPLYTONETADDR:
        !           749:                        msg->replyto_net.addr=(char*)hfield_dat;
        !           750:                        break;
        !           751:                case RECIPIENT:
        !           752:                        msg->to=(char*)hfield_dat;
        !           753:                        break;
        !           754:                case RECIPIENTEXT:
        !           755:                        msg->to_ext=(char*)hfield_dat;
        !           756:                        break;
        !           757:                case RECIPIENTAGENT:
        !           758:                        msg->to_agent=*(ushort *)hfield_dat;
        !           759:                        break;
        !           760:                case RECIPIENTNETTYPE:
        !           761:                        msg->to_net.type=*(ushort *)hfield_dat;
        !           762:                        break;
        !           763:                case RECIPIENTNETADDR:
        !           764:                        msg->to_net.addr=(char*)hfield_dat;
        !           765:                        break;
        !           766:                case SUBJECT:
        !           767:                        msg->subj=(char*)hfield_dat;
        !           768:                        break;
        !           769:                case SMB_SUMMARY:
        !           770:                        msg->summary=(char*)hfield_dat;
        !           771:                        break;
        !           772:                case SMB_EXPIRATION:
        !           773:                        msg->expiration=*(time_t*)hfield_dat;
        !           774:                        break;
        !           775:                case SMB_PRIORITY:
        !           776:                        msg->priority=*(ulong*)hfield_dat;
        !           777:                        break;
        !           778:                case SMB_COST:
        !           779:                        msg->cost=*(ulong*)hfield_dat;
        !           780:                        break;
        !           781:                case RFC822MSGID:
        !           782:                        msg->id=(char*)hfield_dat;
        !           783:                        break;
        !           784:                case RFC822REPLYID:
        !           785:                        msg->reply_id=(char*)hfield_dat;
        !           786:                        break;
        !           787:                case SMTPREVERSEPATH:
        !           788:                        msg->reverse_path=(char*)hfield_dat;
        !           789:                        break;
        !           790:                case USENETPATH:
        !           791:                        msg->path=(char*)hfield_dat;
        !           792:                        break;
        !           793:                case USENETNEWSGROUPS:
        !           794:                        msg->newsgroups=(char*)hfield_dat;
        !           795:                        break;
        !           796:                case FIDOMSGID:
        !           797:                        msg->ftn_msgid=(char*)hfield_dat;
        !           798:                        break;
        !           799:                case FIDOREPLYID:
        !           800:                        msg->ftn_reply=(char*)hfield_dat;
        !           801:                        break;
        !           802:                case FIDOAREA:
        !           803:                        msg->ftn_area=(char*)hfield_dat;
        !           804:                        break;
        !           805:                case FIDOPID:
        !           806:                        msg->ftn_pid=(char*)hfield_dat;
        !           807:                        break;
        !           808:                case FIDOTID:
        !           809:                        msg->ftn_tid=(char*)hfield_dat;
        !           810:                        break;
        !           811:                case FIDOFLAGS:
        !           812:                        msg->ftn_flags=(char*)hfield_dat;
        !           813:                        break;
        !           814:        }
        !           815: }
        !           816: 
        !           817: static void clear_convenience_ptrs(smbmsg_t* msg)
        !           818: {
        !           819:        msg->from=NULL;
        !           820:        msg->from_ext=NULL;
        !           821:        msg->from_org=NULL;
        !           822:        memset(&msg->from_net,0,sizeof(net_t));
        !           823: 
        !           824:        msg->replyto=NULL;
        !           825:        msg->replyto_ext=NULL;
        !           826:        memset(&msg->replyto_net,0,sizeof(net_t));
        !           827: 
        !           828:        msg->to=NULL;
        !           829:        msg->to_ext=NULL;
        !           830:        memset(&msg->to_net,0,sizeof(net_t));
        !           831: 
        !           832:        msg->subj=NULL;
        !           833:        msg->summary=NULL;
        !           834:        msg->id=NULL;
        !           835:        msg->reply_id=NULL;
        !           836:        msg->reverse_path=NULL;
        !           837:        msg->path=NULL;
        !           838:        msg->newsgroups=NULL;
        !           839: 
        !           840:        msg->ftn_msgid=NULL;
        !           841:        msg->ftn_reply=NULL;
        !           842:        msg->ftn_area=NULL;
        !           843:        msg->ftn_pid=NULL;
        !           844:        msg->ftn_tid=NULL;
        !           845:        msg->ftn_flags=NULL;
        !           846: }
        !           847: 
        !           848: /****************************************************************************/
        !           849: /* Read header information into 'msg' structure                             */
        !           850: /* msg->idx.offset must be set before calling this function                            */
        !           851: /* Must call smb_freemsgmem() to free memory allocated for var len strs        */
        !           852: /* Returns 0 on success, non-zero if error                                                                     */
        !           853: /****************************************************************************/
        !           854: int SMBCALL smb_getmsghdr(smb_t* smb, smbmsg_t* msg)
        !           855: {
        !           856:        void    *vp,**vpp;
        !           857:        ushort  i;
        !           858:        ulong   l,offset;
        !           859:        idxrec_t idx;
        !           860: 
        !           861:        if(smb->shd_fp==NULL) {
        !           862:                safe_snprintf(smb->last_error,sizeof(smb->last_error),"msgbase not open");
        !           863:                return(SMB_ERR_NOT_OPEN);
        !           864:        }
        !           865: 
        !           866:        if(!smb_valid_hdr_offset(smb,msg->idx.offset))
        !           867:                return(SMB_ERR_HDR_OFFSET);
        !           868: 
        !           869:        rewind(smb->shd_fp);
        !           870:        if(fseek(smb->shd_fp,msg->idx.offset,SEEK_SET)) {
        !           871:                safe_snprintf(smb->last_error,sizeof(smb->last_error)
        !           872:                        ,"%d '%s' seeking to %lu in header"
        !           873:                        ,get_errno(),STRERROR(get_errno())
        !           874:                        ,msg->idx.offset);
        !           875:                return(SMB_ERR_SEEK);
        !           876:        }
        !           877: 
        !           878:        idx=msg->idx;
        !           879:        offset=msg->offset;
        !           880:        memset(msg,0,sizeof(smbmsg_t));
        !           881:        msg->idx=idx;
        !           882:        msg->offset=offset;
        !           883:        if(smb_fread(smb,&msg->hdr,sizeof(msghdr_t),smb->shd_fp)!=sizeof(msghdr_t)) {
        !           884:                safe_snprintf(smb->last_error,sizeof(smb->last_error)
        !           885:                        ,"%d '%s' reading msg header"
        !           886:                        ,get_errno(),STRERROR(get_errno()));
        !           887:                return(SMB_ERR_READ);
        !           888:        }
        !           889:        if(memcmp(msg->hdr.id,SHD_HEADER_ID,LEN_HEADER_ID)) {
        !           890:                safe_snprintf(smb->last_error,sizeof(smb->last_error)
        !           891:                        ,"corrupt message header ID: %.*s at offset %lu"
        !           892:                        ,LEN_HEADER_ID,msg->hdr.id,msg->idx.offset);
        !           893:                return(SMB_ERR_HDR_ID);
        !           894:        }
        !           895:        if(msg->hdr.version<0x110) {
        !           896:                safe_snprintf(smb->last_error,sizeof(smb->last_error)
        !           897:                        ,"insufficient header version: %X"
        !           898:                        ,msg->hdr.version);
        !           899:                return(SMB_ERR_HDR_VER);
        !           900:        }
        !           901:        l=sizeof(msghdr_t);
        !           902:        if(msg->hdr.total_dfields && (msg->dfield
        !           903:                =(dfield_t *)MALLOC(sizeof(dfield_t)*msg->hdr.total_dfields))==NULL) {
        !           904:                smb_freemsgmem(msg);
        !           905:                safe_snprintf(smb->last_error,sizeof(smb->last_error)
        !           906:                        ,"malloc failure of %d bytes for %d data fields"
        !           907:                        ,(int)sizeof(dfield_t)*msg->hdr.total_dfields, msg->hdr.total_dfields);
        !           908:                return(SMB_ERR_MEM); 
        !           909:        }
        !           910:        i=0;
        !           911:        while(i<msg->hdr.total_dfields && l<(ulong)msg->hdr.length) {
        !           912:                if(smb_fread(smb,&msg->dfield[i],sizeof(dfield_t),smb->shd_fp)!=sizeof(dfield_t)) {
        !           913:                        smb_freemsgmem(msg);
        !           914:                        safe_snprintf(smb->last_error,sizeof(smb->last_error)
        !           915:                                ,"%d '%s' reading data field %d"
        !           916:                                ,get_errno(),STRERROR(get_errno()),i);
        !           917:                        return(SMB_ERR_READ); 
        !           918:                }
        !           919:                i++;
        !           920:                l+=sizeof(dfield_t); 
        !           921:        }
        !           922:        if(i<msg->hdr.total_dfields) {
        !           923:                smb_freemsgmem(msg);
        !           924:                safe_snprintf(smb->last_error,sizeof(smb->last_error)
        !           925:                        ,"insufficient data fields read (%d instead of %d)"
        !           926:                        ,i,msg->hdr.total_dfields);
        !           927:                return(SMB_ERR_READ); 
        !           928:        }
        !           929:        while(l<(ulong)msg->hdr.length) {
        !           930:                i=msg->total_hfields;
        !           931:                if((vpp=(void* *)REALLOC(msg->hfield_dat,sizeof(void* )*(i+1)))==NULL) {
        !           932:                        smb_freemsgmem(msg);
        !           933:                        safe_snprintf(smb->last_error,sizeof(smb->last_error)
        !           934:                                ,"realloc failure of %d bytes for header field data"
        !           935:                                ,(int)sizeof(void*)*(i+1));
        !           936:                        return(SMB_ERR_MEM); 
        !           937:                }
        !           938:                msg->hfield_dat=vpp;
        !           939:                if((vp=(hfield_t *)REALLOC(msg->hfield,sizeof(hfield_t)*(i+1)))==NULL) {
        !           940:                        smb_freemsgmem(msg);
        !           941:                        safe_snprintf(smb->last_error,sizeof(smb->last_error)
        !           942:                                ,"realloc failure of %d bytes for header fields"
        !           943:                                ,(int)sizeof(hfield_t)*(i+1));
        !           944:                        return(SMB_ERR_MEM); 
        !           945:                }
        !           946:                msg->hfield=vp;
        !           947:                if(smb_fread(smb,&msg->hfield[i],sizeof(hfield_t),smb->shd_fp)!=sizeof(hfield_t)) {
        !           948:                        smb_freemsgmem(msg);
        !           949:                        safe_snprintf(smb->last_error,sizeof(smb->last_error)
        !           950:                                ,"%d '%s' reading header field"
        !           951:                                ,get_errno(),STRERROR(get_errno()));
        !           952:                        return(SMB_ERR_READ); 
        !           953:                }
        !           954:                l+=sizeof(hfield_t);
        !           955:                if((msg->hfield_dat[i]=(char*)MALLOC(msg->hfield[i].length+1))
        !           956:                        ==NULL) {                       /* Allocate 1 extra for ASCIIZ terminator */
        !           957:                        safe_snprintf(smb->last_error,sizeof(smb->last_error)
        !           958:                                ,"malloc failure of %d bytes for header field %d"
        !           959:                                ,msg->hfield[i].length+1, i);
        !           960:                        smb_freemsgmem(msg);  /* or 0 length field */
        !           961:                        return(SMB_ERR_MEM); 
        !           962:                }
        !           963:                msg->total_hfields++;
        !           964:                memset(msg->hfield_dat[i],0,msg->hfield[i].length+1);  /* init to NULL */
        !           965:                if(msg->hfield[i].length
        !           966:                        && smb_fread(smb,msg->hfield_dat[i],msg->hfield[i].length,smb->shd_fp)
        !           967:                                !=(size_t)msg->hfield[i].length) {
        !           968:                        smb_freemsgmem(msg);
        !           969:                        safe_snprintf(smb->last_error,sizeof(smb->last_error)
        !           970:                                ,"%d '%s' reading header field data"
        !           971:                                ,get_errno(),STRERROR(get_errno()));
        !           972:                        return(SMB_ERR_READ); 
        !           973:                }
        !           974:                set_convenience_ptr(msg,msg->hfield[i].type,msg->hfield_dat[i]);
        !           975: 
        !           976:                l+=msg->hfield[i].length; 
        !           977:        }
        !           978: 
        !           979:        /* These convenience pointers must point to something */
        !           980:        if(msg->from==NULL)     msg->from=nulstr;
        !           981:        if(msg->to==NULL)       msg->to=nulstr;
        !           982:        if(msg->subj==NULL)     msg->subj=nulstr;
        !           983: 
        !           984:        /* If no reverse path specified, use sender's address */
        !           985:        if(msg->reverse_path == NULL)
        !           986:                msg->reverse_path = msg->from_net.addr;
        !           987: 
        !           988:        return(SMB_SUCCESS);
        !           989: }
        !           990: 
        !           991: /****************************************************************************/
        !           992: /* Frees memory allocated for variable-length header fields in 'msg'        */
        !           993: /****************************************************************************/
        !           994: void SMBCALL smb_freemsghdrmem(smbmsg_t* msg)
        !           995: {
        !           996:        ushort  i;
        !           997: 
        !           998:        for(i=0;i<msg->total_hfields;i++)
        !           999:                if(msg->hfield_dat[i]) {
        !          1000:                        FREE(msg->hfield_dat[i]);
        !          1001:                        msg->hfield_dat[i]=NULL;
        !          1002:                }
        !          1003:        msg->total_hfields=0;
        !          1004:        if(msg->hfield) {
        !          1005:                FREE(msg->hfield);
        !          1006:                msg->hfield=NULL;
        !          1007:        }
        !          1008:        if(msg->hfield_dat) {
        !          1009:                FREE(msg->hfield_dat);
        !          1010:                msg->hfield_dat=NULL;
        !          1011:        }
        !          1012:        clear_convenience_ptrs(msg);    /* don't leave pointers to freed memory */
        !          1013: }
        !          1014: 
        !          1015: /****************************************************************************/
        !          1016: /* Frees memory allocated for 'msg'                                         */
        !          1017: /****************************************************************************/
        !          1018: void SMBCALL smb_freemsgmem(smbmsg_t* msg)
        !          1019: {
        !          1020:        if(msg->dfield) {
        !          1021:                FREE(msg->dfield);
        !          1022:                msg->dfield=NULL;
        !          1023:        }
        !          1024:        msg->hdr.total_dfields=0;
        !          1025:        smb_freemsghdrmem(msg);
        !          1026: }
        !          1027: 
        !          1028: /****************************************************************************/
        !          1029: /* Copies memory allocated for 'srcmsg' to 'msg'                                                       */
        !          1030: /****************************************************************************/
        !          1031: int SMBCALL smb_copymsgmem(smb_t* smb, smbmsg_t* msg, smbmsg_t* srcmsg)
        !          1032: {
        !          1033:        int i;
        !          1034: 
        !          1035:        memcpy(msg,srcmsg,sizeof(smbmsg_t));
        !          1036: 
        !          1037:        /* data field types/lengths */
        !          1038:        if(msg->hdr.total_dfields>0) {
        !          1039:                if((msg->dfield=(dfield_t *)MALLOC(msg->hdr.total_dfields*sizeof(dfield_t)))==NULL) {
        !          1040:                        if(smb!=NULL)
        !          1041:                                safe_snprintf(smb->last_error,sizeof(smb->last_error)
        !          1042:                                        ,"malloc failure of %d bytes for %d data fields"
        !          1043:                                        ,msg->hdr.total_dfields*sizeof(dfield_t), msg->hdr.total_dfields);
        !          1044:                        return(SMB_ERR_MEM);
        !          1045:                }
        !          1046:                memcpy(msg->dfield,srcmsg->dfield,msg->hdr.total_dfields*sizeof(dfield_t));
        !          1047:        }
        !          1048: 
        !          1049:        /* header field types/lengths */
        !          1050:        if(msg->total_hfields>0) {
        !          1051:                if((msg->hfield=(hfield_t *)MALLOC(msg->total_hfields*sizeof(hfield_t)))==NULL) {
        !          1052:                        if(smb!=NULL)
        !          1053:                                safe_snprintf(smb->last_error,sizeof(smb->last_error)
        !          1054:                                        ,"malloc failure of %d bytes for %d header fields"
        !          1055:                                        ,msg->total_hfields*sizeof(hfield_t), msg->total_hfields);
        !          1056:                        return(SMB_ERR_MEM);
        !          1057:                }
        !          1058:                memcpy(msg->hfield,srcmsg->hfield,msg->total_hfields*sizeof(hfield_t));
        !          1059: 
        !          1060:                /* header field data */
        !          1061:                if((msg->hfield_dat=(void**)MALLOC(msg->total_hfields*sizeof(void*)))==NULL) {
        !          1062:                        if(smb!=NULL)
        !          1063:                                safe_snprintf(smb->last_error,sizeof(smb->last_error)
        !          1064:                                        ,"malloc failure of %d bytes for %d header fields"
        !          1065:                                        ,msg->total_hfields*sizeof(void*), msg->total_hfields);
        !          1066:                        return(SMB_ERR_MEM);
        !          1067:                }
        !          1068: 
        !          1069:                for(i=0;i<msg->total_hfields;i++) {
        !          1070:                        if((msg->hfield_dat[i]=(void*)MALLOC(msg->hfield[i].length+1))==NULL) {
        !          1071:                                if(smb!=NULL)
        !          1072:                                        safe_snprintf(smb->last_error,sizeof(smb->last_error)
        !          1073:                                                ,"malloc failure of %d bytes for header field #%d"
        !          1074:                                                ,msg->hfield[i].length+1, i+1);
        !          1075:                                return(SMB_ERR_MEM);
        !          1076:                        }
        !          1077:                        memset(msg->hfield_dat[i],0,msg->hfield[i].length+1);
        !          1078:                        memcpy(msg->hfield_dat[i],srcmsg->hfield_dat[i],msg->hfield[i].length);
        !          1079:                }
        !          1080:        }
        !          1081: 
        !          1082:        return(SMB_SUCCESS);
        !          1083: }
        !          1084: 
        !          1085: /****************************************************************************/
        !          1086: /* Unlocks header for 'msg'                                                 */
        !          1087: /****************************************************************************/
        !          1088: int SMBCALL smb_unlockmsghdr(smb_t* smb, smbmsg_t* msg)
        !          1089: {
        !          1090:        if(smb->shd_fp==NULL) {
        !          1091:                safe_snprintf(smb->last_error,sizeof(smb->last_error),"msgbase not open");
        !          1092:                return(SMB_ERR_NOT_OPEN);
        !          1093:        }
        !          1094:        if(!smb_valid_hdr_offset(smb,msg->idx.offset))
        !          1095:                return(SMB_ERR_HDR_OFFSET);
        !          1096:        return(unlock(fileno(smb->shd_fp),msg->idx.offset,sizeof(msghdr_t)));
        !          1097: }
        !          1098: 
        !          1099: 
        !          1100: /****************************************************************************/
        !          1101: /* Adds a header field to the 'msg' structure (in memory only)              */
        !          1102: /****************************************************************************/
        !          1103: int SMBCALL smb_hfield(smbmsg_t* msg, ushort type, size_t length, void* data)
        !          1104: {
        !          1105:        void**          vpp;
        !          1106:        hfield_t*       hp;
        !          1107:        int i;
        !          1108: 
        !          1109:        if(smb_getmsghdrlen(msg)+sizeof(hfield_t)+length>SMB_MAX_HDR_LEN)
        !          1110:                return(SMB_ERR_HDR_LEN);
        !          1111: 
        !          1112:        i=msg->total_hfields;
        !          1113:        if((hp=(hfield_t *)REALLOC(msg->hfield,sizeof(hfield_t)*(i+1)))==NULL) 
        !          1114:                return(SMB_ERR_MEM);
        !          1115: 
        !          1116:        msg->hfield=hp;
        !          1117:        if((vpp=(void* *)REALLOC(msg->hfield_dat,sizeof(void* )*(i+1)))==NULL) 
        !          1118:                return(SMB_ERR_MEM);
        !          1119:        
        !          1120:        msg->hfield_dat=vpp;
        !          1121:        msg->total_hfields++;
        !          1122:        msg->hfield[i].type=type;
        !          1123:        msg->hfield[i].length=length;
        !          1124:        if(length) {
        !          1125:                if((msg->hfield_dat[i]=(void* )MALLOC(length+1))==NULL) 
        !          1126:                        return(SMB_ERR_MEM);    /* Allocate 1 extra for ASCIIZ terminator */
        !          1127:                memset(msg->hfield_dat[i],0,length+1);
        !          1128:                memcpy(msg->hfield_dat[i],data,length); 
        !          1129:                set_convenience_ptr(msg,type,msg->hfield_dat[i]);
        !          1130:        }
        !          1131:        else
        !          1132:                msg->hfield_dat[i]=NULL;
        !          1133: 
        !          1134:        return(SMB_SUCCESS);
        !          1135: }
        !          1136: 
        !          1137: /****************************************************************************/
        !          1138: /* Adds a list of header fields to the 'msg' structure (in memory only)     */
        !          1139: /****************************************************************************/
        !          1140: int    SMBCALL smb_hfield_addlist(smbmsg_t* msg, hfield_t** hfield_list, void** hfield_dat)
        !          1141: {
        !          1142:        int                     retval;
        !          1143:        unsigned        n;
        !          1144: 
        !          1145:        if(hfield_list==NULL)
        !          1146:                return(SMB_FAILURE);
        !          1147: 
        !          1148:        for(n=0;hfield_list[n]!=NULL;n++)
        !          1149:                if((retval=smb_hfield(msg
        !          1150:                        ,hfield_list[n]->type,hfield_list[n]->length,hfield_dat[n]))!=SMB_SUCCESS)
        !          1151:                        return(retval);
        !          1152: 
        !          1153:        return(SMB_SUCCESS);
        !          1154: }
        !          1155: 
        !          1156: /****************************************************************************/
        !          1157: /* Convenience function to add an ASCIIZ string header field                           */
        !          1158: /****************************************************************************/
        !          1159: int SMBCALL smb_hfield_str(smbmsg_t* msg, ushort type, const char* str)
        !          1160: {
        !          1161:        return smb_hfield(msg, type, strlen(str), (void*)str);
        !          1162: }
        !          1163: 
        !          1164: /****************************************************************************/
        !          1165: /* Convenience function to add an ASCIIZ string header field                           */
        !          1166: /****************************************************************************/
        !          1167: int    SMBCALL smb_hfield_netaddr(smbmsg_t* msg, ushort type, const char* str, ushort* nettype)
        !          1168: {
        !          1169:        fidoaddr_t      sys_addr = {0,0,0,0};   /* replace unspecified fields with 0 (don't assume 1:1/1) */
        !          1170:        fidoaddr_t      fidoaddr;
        !          1171:        ushort          tmp_nettype=NET_UNKNOWN;
        !          1172: 
        !          1173:        if(nettype==NULL)
        !          1174:                nettype=&tmp_nettype;
        !          1175:        if(*nettype==NET_UNKNOWN)
        !          1176:                *nettype=smb_netaddr_type(str);
        !          1177:        if(*nettype==NET_FIDO) {
        !          1178:                fidoaddr=smb_atofaddr(&sys_addr,str);
        !          1179:                return smb_hfield_bin(msg,type,fidoaddr);
        !          1180:        } else
        !          1181:                return smb_hfield_str(msg,type,str);
        !          1182: }
        !          1183: 
        !          1184: /****************************************************************************/
        !          1185: /* Appends data to an existing header field (in memory only)                           */
        !          1186: /****************************************************************************/
        !          1187: int SMBCALL smb_hfield_append(smbmsg_t* msg, ushort type, size_t length, void* data)
        !          1188: {
        !          1189:        int             i;
        !          1190:        BYTE*   p;
        !          1191: 
        !          1192:        if(length==0)   /* nothing to append */
        !          1193:                return(SMB_SUCCESS);
        !          1194: 
        !          1195:        if(msg->total_hfields<1)
        !          1196:                return(SMB_ERR_NOT_FOUND);
        !          1197: 
        !          1198:        /* search for the last header field of this type */
        !          1199:        for(i=msg->total_hfields-1;i>=0;i--)
        !          1200:                if(msg->hfield[i].type == type)
        !          1201:                        break;
        !          1202:        if(i<0)
        !          1203:                return(SMB_ERR_NOT_FOUND);
        !          1204: 
        !          1205:        if(smb_getmsghdrlen(msg)+length>SMB_MAX_HDR_LEN)
        !          1206:                return(SMB_ERR_HDR_LEN);
        !          1207: 
        !          1208:        if((p=(BYTE*)REALLOC(msg->hfield_dat[i],msg->hfield[i].length+length+1))==NULL) 
        !          1209:                return(SMB_ERR_MEM);    /* Allocate 1 extra for ASCIIZ terminator */
        !          1210: 
        !          1211:        msg->hfield_dat[i]=p;
        !          1212:        p+=msg->hfield[i].length;       /* skip existing data */
        !          1213:        memset(p,0,length+1);
        !          1214:        memcpy(p,data,length);          /* append */
        !          1215:        msg->hfield[i].length+=length;
        !          1216:        set_convenience_ptr(msg,type,msg->hfield_dat[i]);
        !          1217: 
        !          1218:        return(SMB_SUCCESS);
        !          1219: }
        !          1220: 
        !          1221: /****************************************************************************/
        !          1222: /* Appends data to an existing ASCIIZ header field (in memory only)                    */
        !          1223: /****************************************************************************/
        !          1224: int SMBCALL smb_hfield_append_str(smbmsg_t* msg, ushort type, const char* str)
        !          1225: {
        !          1226:        return smb_hfield_append(msg, type, strlen(str), (void*)str);
        !          1227: }
        !          1228: 
        !          1229: /****************************************************************************/
        !          1230: /* Searches for a specific header field (by type) and returns it                       */
        !          1231: /****************************************************************************/
        !          1232: void* SMBCALL smb_get_hfield(smbmsg_t* msg, ushort type, hfield_t* hfield)
        !          1233: {
        !          1234:        int i;
        !          1235: 
        !          1236:        for(i=0;i<msg->total_hfields;i++)
        !          1237:                if(msg->hfield[i].type == type) {
        !          1238:                        if(hfield != NULL)
        !          1239:                                *hfield = msg->hfield[i];
        !          1240:                        return(msg->hfield_dat[i]);
        !          1241:                }
        !          1242: 
        !          1243:        return(NULL);
        !          1244: }
        !          1245: 
        !          1246: /****************************************************************************/
        !          1247: /* Adds a data field to the 'msg' structure (in memory only)                */
        !          1248: /* Automatically figures out the offset into the data buffer from existing     */
        !          1249: /* dfield lengths                                                                                                                      */
        !          1250: /****************************************************************************/
        !          1251: int SMBCALL smb_dfield(smbmsg_t* msg, ushort type, ulong length)
        !          1252: {
        !          1253:        dfield_t* dp;
        !          1254:        int i,j;
        !          1255: 
        !          1256:        i=msg->hdr.total_dfields;
        !          1257:        if((dp=(dfield_t *)REALLOC(msg->dfield,sizeof(dfield_t)*(i+1)))==NULL) 
        !          1258:                return(SMB_ERR_MEM);
        !          1259:        
        !          1260:        msg->dfield=dp;
        !          1261:        msg->hdr.total_dfields++;
        !          1262:        msg->dfield[i].type=type;
        !          1263:        msg->dfield[i].length=length;
        !          1264:        for(j=msg->dfield[i].offset=0;j<i;j++)
        !          1265:                msg->dfield[i].offset+=msg->dfield[j].length;
        !          1266:        return(SMB_SUCCESS);
        !          1267: }
        !          1268: 
        !          1269: /****************************************************************************/
        !          1270: /* Checks CRC history file for duplicate crc. If found, returns 1.                     */
        !          1271: /* If no dupe, adds to CRC history and returns 0, or negative if error.        */
        !          1272: /****************************************************************************/
        !          1273: int SMBCALL smb_addcrc(smb_t* smb, ulong crc)
        !          1274: {
        !          1275:        char    str[MAX_PATH+1];
        !          1276:        int     file;
        !          1277:        int             wr;
        !          1278:        long    length;
        !          1279:        long    newlen;
        !          1280:        ulong   l,*buf;
        !          1281:        time_t  start=0;
        !          1282: 
        !          1283:        if(!smb->status.max_crcs)
        !          1284:                return(SMB_SUCCESS);
        !          1285: 
        !          1286:        SAFEPRINTF(str,"%s.sch",smb->file);
        !          1287:        while(1) {
        !          1288:                if((file=sopen(str,O_RDWR|O_CREAT|O_BINARY,SH_DENYRW,S_IREAD|S_IWRITE))!=-1)
        !          1289:                        break;
        !          1290:                if(get_errno()!=EACCES && get_errno()!=EAGAIN) {
        !          1291:                        safe_snprintf(smb->last_error,sizeof(smb->last_error)
        !          1292:                                ,"%d '%s' opening %s"
        !          1293:                                ,get_errno(),STRERROR(get_errno()),str);
        !          1294:                        return(SMB_ERR_OPEN);
        !          1295:                }
        !          1296:                if(!start)
        !          1297:                        start=time(NULL);
        !          1298:                else
        !          1299:                        if(time(NULL)-start>=(time_t)smb->retry_time) {
        !          1300:                                safe_snprintf(smb->last_error,sizeof(smb->last_error)
        !          1301:                                        ,"timeout opening %s (retry_time=%ld)"
        !          1302:                                        ,str,smb->retry_time);
        !          1303:                                return(SMB_ERR_TIMEOUT); 
        !          1304:                        }
        !          1305:                SLEEP(smb->retry_delay);
        !          1306:        }
        !          1307: 
        !          1308:        length=filelength(file);
        !          1309:        if(length<0L || length%sizeof(long)) {
        !          1310:                close(file);
        !          1311:                safe_snprintf(smb->last_error,sizeof(smb->last_error)
        !          1312:                        ,"invalid file length: %ld", length);
        !          1313:                return(SMB_ERR_FILE_LEN); 
        !          1314:        }
        !          1315: 
        !          1316:        if(length!=0) {
        !          1317:                if((buf=(ulong*)MALLOC(length))==NULL) {
        !          1318:                        close(file);
        !          1319:                        safe_snprintf(smb->last_error,sizeof(smb->last_error)
        !          1320:                                ,"malloc failure of %ld bytes"
        !          1321:                                ,length);
        !          1322:                        return(SMB_ERR_MEM); 
        !          1323:                }
        !          1324: 
        !          1325:                if(read(file,buf,length)!=length) {
        !          1326:                        close(file);
        !          1327:                        FREE(buf);
        !          1328:                        safe_snprintf(smb->last_error,sizeof(smb->last_error)
        !          1329:                                ,"%d '%s' reading %ld bytes"
        !          1330:                                ,get_errno(),STRERROR(get_errno()),length);
        !          1331:                        return(SMB_ERR_READ);
        !          1332:                }
        !          1333: 
        !          1334:                for(l=0;l<length/sizeof(long);l++)
        !          1335:                        if(crc==buf[l])
        !          1336:                                break;
        !          1337:                if(l<length/sizeof(long)) {                                     /* Dupe CRC found */
        !          1338:                        close(file);
        !          1339:                        FREE(buf);
        !          1340:                        safe_snprintf(smb->last_error,sizeof(smb->last_error)
        !          1341:                                ,"duplicate message text CRC detected");
        !          1342:                        return(SMB_DUPE_MSG);
        !          1343:                } 
        !          1344: 
        !          1345:                if(length>=(long)(smb->status.max_crcs*sizeof(long))) {
        !          1346:                        newlen=(smb->status.max_crcs-1)*sizeof(long);
        !          1347:                        chsize(file,0); /* truncate it */
        !          1348:                        lseek(file,0L,SEEK_SET);
        !          1349:                        write(file,buf+(length-newlen),newlen); 
        !          1350:                }
        !          1351:                FREE(buf);
        !          1352:        }
        !          1353:        wr=write(file,&crc,sizeof(crc));        /* Write to the end */
        !          1354:        close(file);
        !          1355: 
        !          1356:        if(wr!=sizeof(crc)) {   
        !          1357:                safe_snprintf(smb->last_error,sizeof(smb->last_error)
        !          1358:                        ,"%d '%s' writing %u bytes"
        !          1359:                        ,get_errno(),STRERROR(get_errno()),sizeof(crc));
        !          1360:                return(SMB_ERR_WRITE);
        !          1361:        }
        !          1362: 
        !          1363:        return(SMB_SUCCESS);
        !          1364: }
        !          1365: 
        !          1366: /****************************************************************************/
        !          1367: /* Creates a new message header record in the header file.                                     */
        !          1368: /* If storage is SMB_SELFPACK, self-packing conservative allocation is used */
        !          1369: /* If storage is SMB_FASTALLOC, fast allocation is used                                        */
        !          1370: /* If storage is SMB_HYPERALLOC, no allocation tables are used (fastest)       */
        !          1371: /* This function will UN-lock the SMB header                                                           */
        !          1372: /****************************************************************************/
        !          1373: int SMBCALL smb_addmsghdr(smb_t* smb, smbmsg_t* msg, int storage)
        !          1374: {
        !          1375:        int             i;
        !          1376:        long    l;
        !          1377:        ulong   hdrlen;
        !          1378: 
        !          1379:        if(smb->shd_fp==NULL) {
        !          1380:                safe_snprintf(smb->last_error,sizeof(smb->last_error),"msgbase not open");
        !          1381:                return(SMB_ERR_NOT_OPEN);
        !          1382:        }
        !          1383: 
        !          1384:        if(!smb->locked && smb_locksmbhdr(smb)!=SMB_SUCCESS)
        !          1385:                return(SMB_ERR_LOCK);
        !          1386: 
        !          1387:        hdrlen=smb_getmsghdrlen(msg);
        !          1388:        if(hdrlen>SMB_MAX_HDR_LEN) { /* headers are limited to 64k in size */
        !          1389:                smb_unlocksmbhdr(smb);
        !          1390:                safe_snprintf(smb->last_error,sizeof(smb->last_error)
        !          1391:                        ,"illegal message header length (%lu > %u)"
        !          1392:                        ,hdrlen,SMB_MAX_HDR_LEN);
        !          1393:                return(SMB_ERR_HDR_LEN);
        !          1394:        }
        !          1395: 
        !          1396:        if((i=smb_getstatus(smb))!=SMB_SUCCESS) {
        !          1397:                smb_unlocksmbhdr(smb);
        !          1398:                return(i);
        !          1399:        }
        !          1400:        msg->idx.number=msg->hdr.number=smb->status.last_msg+1;
        !          1401: 
        !          1402:        /* This is *not* a dupe-check */
        !          1403:        if(!(msg->flags&MSG_FLAG_HASHED) /* not already hashed */
        !          1404:                && (i=smb_hashmsg(smb,msg,NULL,/* update? */TRUE))!=SMB_SUCCESS) {
        !          1405:                smb_unlocksmbhdr(smb);
        !          1406:                return(i);      /* error updating hash table */
        !          1407:        }
        !          1408: 
        !          1409:        if(storage!=SMB_HYPERALLOC && (i=smb_open_ha(smb))!=SMB_SUCCESS) {
        !          1410:                smb_unlocksmbhdr(smb);
        !          1411:                return(i);
        !          1412:        }
        !          1413: 
        !          1414:        if(msg->hdr.version==0)
        !          1415:                msg->hdr.version=SMB_VERSION;
        !          1416:        msg->hdr.length=(ushort)hdrlen;
        !          1417:        if(storage==SMB_HYPERALLOC)
        !          1418:                l=smb_hallochdr(smb);
        !          1419:        else if(storage==SMB_FASTALLOC)
        !          1420:                l=smb_fallochdr(smb,msg->hdr.length);
        !          1421:        else
        !          1422:                l=smb_allochdr(smb,msg->hdr.length);
        !          1423:        if(storage!=SMB_HYPERALLOC)
        !          1424:                smb_close_ha(smb);
        !          1425:        if(l<0) {
        !          1426:                smb_unlocksmbhdr(smb);
        !          1427:                return(l); 
        !          1428:        }
        !          1429: 
        !          1430:        msg->idx.offset=smb->status.header_offset+l;
        !          1431:        msg->idx.time=msg->hdr.when_imported.time;
        !          1432:        msg->idx.attr=msg->hdr.attr;
        !          1433:        msg->offset=smb->status.total_msgs;
        !          1434:        i=smb_putmsg(smb,msg);
        !          1435:        if(i==SMB_SUCCESS) {
        !          1436:                smb->status.last_msg++;
        !          1437:                smb->status.total_msgs++;
        !          1438:                smb_putstatus(smb);
        !          1439:        }
        !          1440:        smb_unlocksmbhdr(smb);
        !          1441:        return(i);
        !          1442: }
        !          1443: 
        !          1444: 
        !          1445: /****************************************************************************/
        !          1446: /* Writes both header and index information for msg 'msg'                   */
        !          1447: /****************************************************************************/
        !          1448: int SMBCALL smb_putmsg(smb_t* smb, smbmsg_t* msg)
        !          1449: {
        !          1450:        int i;
        !          1451: 
        !          1452:        i=smb_putmsghdr(smb,msg);
        !          1453:        if(i)
        !          1454:                return(i);
        !          1455:        return(smb_putmsgidx(smb,msg));
        !          1456: }
        !          1457: 
        !          1458: /****************************************************************************/
        !          1459: /* Writes index information for 'msg'                                       */
        !          1460: /* msg->idx                                                                                                                            */
        !          1461: /* and msg->offset must be set prior to calling to this function                       */
        !          1462: /* Returns 0 if everything ok                                               */
        !          1463: /****************************************************************************/
        !          1464: int SMBCALL smb_putmsgidx(smb_t* smb, smbmsg_t* msg)
        !          1465: {
        !          1466:        if(smb->sid_fp==NULL) {
        !          1467:                safe_snprintf(smb->last_error,sizeof(smb->last_error),"index not open");
        !          1468:                return(SMB_ERR_NOT_OPEN);
        !          1469:        }
        !          1470:        clearerr(smb->sid_fp);
        !          1471:        if(fseek(smb->sid_fp,msg->offset*sizeof(idxrec_t),SEEK_SET)) {
        !          1472:                safe_snprintf(smb->last_error,sizeof(smb->last_error)
        !          1473:                        ,"%d '%s' seeking to %u in header"
        !          1474:                        ,get_errno(),STRERROR(get_errno())
        !          1475:                        ,(unsigned)(msg->offset*sizeof(idxrec_t)));
        !          1476:                return(SMB_ERR_SEEK);
        !          1477:        }
        !          1478:        if(!fwrite(&msg->idx,sizeof(idxrec_t),1,smb->sid_fp)) {
        !          1479:                safe_snprintf(smb->last_error,sizeof(smb->last_error)
        !          1480:                        ,"%d '%s' writing index"
        !          1481:                        ,get_errno(),STRERROR(get_errno()));
        !          1482:                return(SMB_ERR_WRITE);
        !          1483:        }
        !          1484:        fflush(smb->sid_fp);
        !          1485:        return(SMB_SUCCESS);
        !          1486: }
        !          1487: 
        !          1488: /****************************************************************************/
        !          1489: /* Writes header information for 'msg'                                      */
        !          1490: /* msg->hdr.length                                                                                                                     */
        !          1491: /* msg->idx.offset                                                                                                                     */
        !          1492: /* and msg->offset must be set prior to calling to this function                       */
        !          1493: /* Returns 0 if everything ok                                               */
        !          1494: /****************************************************************************/
        !          1495: int SMBCALL smb_putmsghdr(smb_t* smb, smbmsg_t* msg)
        !          1496: {
        !          1497:        ushort  i;
        !          1498:        ulong   hdrlen;
        !          1499: 
        !          1500:        if(smb->shd_fp==NULL) {
        !          1501:                safe_snprintf(smb->last_error,sizeof(smb->last_error),"msgbase not open");
        !          1502:                return(SMB_ERR_NOT_OPEN);
        !          1503:        }
        !          1504: 
        !          1505:        if(!smb_valid_hdr_offset(smb,msg->idx.offset))
        !          1506:                return(SMB_ERR_HDR_OFFSET);
        !          1507: 
        !          1508:        clearerr(smb->shd_fp);
        !          1509:        if(fseek(smb->shd_fp,msg->idx.offset,SEEK_SET)) {
        !          1510:                safe_snprintf(smb->last_error,sizeof(smb->last_error)
        !          1511:                        ,"%d '%s' seeking to %lu in index"
        !          1512:                        ,get_errno(),STRERROR(get_errno()),msg->idx.offset);
        !          1513:                return(SMB_ERR_SEEK);
        !          1514:        }
        !          1515:        /* Verify that the number of blocks required to stored the actual 
        !          1516:           (calculated) header length does not exceed the number allocated. */
        !          1517:        hdrlen=smb_getmsghdrlen(msg);
        !          1518:        if(hdrlen>SMB_MAX_HDR_LEN) { /* headers are limited to 64k in size */
        !          1519:                safe_snprintf(smb->last_error,sizeof(smb->last_error)
        !          1520:                        ,"illegal message header length (%lu > %u)"
        !          1521:                        ,hdrlen,SMB_MAX_HDR_LEN);
        !          1522:                return(SMB_ERR_HDR_LEN);
        !          1523:        }
        !          1524:        if(smb_hdrblocks(hdrlen) > smb_hdrblocks(msg->hdr.length)) {
        !          1525:                safe_snprintf(smb->last_error,sizeof(smb->last_error)
        !          1526:                        ,"illegal header length increase: %lu (%lu blocks) vs %hu (%lu blocks)"
        !          1527:                        ,hdrlen, smb_hdrblocks(hdrlen)
        !          1528:                        ,msg->hdr.length, smb_hdrblocks(msg->hdr.length));
        !          1529:                return(SMB_ERR_HDR_LEN);
        !          1530:        }
        !          1531:        msg->hdr.length=(ushort)hdrlen; /* store the actual header length */
        !          1532:        /**********************************/
        !          1533:        /* Set the message header ID here */
        !          1534:        /**********************************/
        !          1535:        memcpy(&msg->hdr.id,SHD_HEADER_ID,LEN_HEADER_ID);
        !          1536: 
        !          1537:        /************************************************/
        !          1538:        /* Write the fixed portion of the header record */
        !          1539:        /************************************************/
        !          1540:        if(!fwrite(&msg->hdr,sizeof(msghdr_t),1,smb->shd_fp)) {
        !          1541:                safe_snprintf(smb->last_error,sizeof(smb->last_error)
        !          1542:                        ,"%d '%s' writing fixed portion of header record"
        !          1543:                        ,get_errno(),STRERROR(get_errno()));
        !          1544:                return(SMB_ERR_WRITE);
        !          1545:        }
        !          1546: 
        !          1547:        /************************************************/
        !          1548:        /* Write the data fields (each is fixed length) */
        !          1549:        /************************************************/
        !          1550:        for(i=0;i<msg->hdr.total_dfields;i++)
        !          1551:                if(!fwrite(&msg->dfield[i],sizeof(dfield_t),1,smb->shd_fp)) {
        !          1552:                        safe_snprintf(smb->last_error,sizeof(smb->last_error)
        !          1553:                                ,"%d '%s' writing data field"
        !          1554:                                ,get_errno(),STRERROR(get_errno()));
        !          1555:                        return(SMB_ERR_WRITE);
        !          1556:                }
        !          1557:        /*******************************************/
        !          1558:        /* Write the variable length header fields */
        !          1559:        /*******************************************/
        !          1560:        for(i=0;i<msg->total_hfields;i++) {
        !          1561:                if(!fwrite(&msg->hfield[i],sizeof(hfield_t),1,smb->shd_fp)) {
        !          1562:                        safe_snprintf(smb->last_error,sizeof(smb->last_error)
        !          1563:                                ,"%d '%s' writing header field"
        !          1564:                                ,get_errno(),STRERROR(get_errno()));
        !          1565:                        return(SMB_ERR_WRITE);
        !          1566:                }
        !          1567:                if(msg->hfield[i].length                                         /* more then 0 bytes long */
        !          1568:                        && !fwrite(msg->hfield_dat[i],msg->hfield[i].length,1,smb->shd_fp)) {
        !          1569:                        safe_snprintf(smb->last_error,sizeof(smb->last_error)
        !          1570:                                ,"%d '%s' writing header field data"
        !          1571:                                ,get_errno(),STRERROR(get_errno()));
        !          1572:                        return(SMB_ERR_WRITE); 
        !          1573:                }
        !          1574:        }
        !          1575: 
        !          1576:        while(hdrlen%SHD_BLOCK_LEN) {
        !          1577:                if(fputc(0,smb->shd_fp)!=0) {
        !          1578:                        safe_snprintf(smb->last_error,sizeof(smb->last_error)
        !          1579:                                ,"%d '%s' padding header block"
        !          1580:                                ,get_errno(),STRERROR(get_errno()));
        !          1581:                        return(SMB_ERR_WRITE);                     /* pad block with NULL */
        !          1582:                }
        !          1583:                hdrlen++; 
        !          1584:        }
        !          1585:        fflush(smb->shd_fp);
        !          1586:        return(SMB_SUCCESS);
        !          1587: }
        !          1588: 
        !          1589: /****************************************************************************/
        !          1590: /* Creates a sub-board's initial header file                                */
        !          1591: /* Truncates and deletes other associated SMB files                                            */
        !          1592: /****************************************************************************/
        !          1593: int SMBCALL smb_create(smb_t* smb)
        !          1594: {
        !          1595:     char        str[MAX_PATH+1];
        !          1596:        smbhdr_t        hdr;
        !          1597: 
        !          1598:        if(smb->shd_fp==NULL || smb->sdt_fp==NULL || smb->sid_fp==NULL) {
        !          1599:                safe_snprintf(smb->last_error,sizeof(smb->last_error),"msgbase not open");
        !          1600:                return(SMB_ERR_NOT_OPEN);
        !          1601:        }
        !          1602:        if(filelength(fileno(smb->shd_fp))>=(long)(sizeof(smbhdr_t)+sizeof(smbstatus_t))
        !          1603:                && smb_locksmbhdr(smb)!=SMB_SUCCESS)  /* header exists, so lock it */
        !          1604:                return(SMB_ERR_LOCK);
        !          1605:        memset(&hdr,0,sizeof(smbhdr_t));
        !          1606:        memcpy(hdr.id,SMB_HEADER_ID,LEN_HEADER_ID);     
        !          1607:        hdr.version=SMB_VERSION;
        !          1608:        hdr.length=sizeof(smbhdr_t)+sizeof(smbstatus_t);
        !          1609:        smb->status.last_msg=smb->status.total_msgs=0;
        !          1610:        smb->status.header_offset=sizeof(smbhdr_t)+sizeof(smbstatus_t);
        !          1611:        rewind(smb->shd_fp);
        !          1612:        fwrite(&hdr,1,sizeof(smbhdr_t),smb->shd_fp);
        !          1613:        fwrite(&(smb->status),1,sizeof(smbstatus_t),smb->shd_fp);
        !          1614:        rewind(smb->shd_fp);
        !          1615:        chsize(fileno(smb->shd_fp),sizeof(smbhdr_t)+sizeof(smbstatus_t));
        !          1616:        fflush(smb->shd_fp);
        !          1617: 
        !          1618:        rewind(smb->sdt_fp);
        !          1619:        chsize(fileno(smb->sdt_fp),0L);
        !          1620:        rewind(smb->sid_fp);
        !          1621:        chsize(fileno(smb->sid_fp),0L);
        !          1622: 
        !          1623:        SAFEPRINTF(str,"%s.sda",smb->file);
        !          1624:        remove(str);                                            /* if it exists, delete it */
        !          1625:        SAFEPRINTF(str,"%s.sha",smb->file);
        !          1626:        remove(str);                        /* if it exists, delete it */
        !          1627:        SAFEPRINTF(str,"%s.sch",smb->file);
        !          1628:        remove(str);
        !          1629:        SAFEPRINTF(str,"%s.hash",smb->file);
        !          1630:        remove(str);
        !          1631:        smb_unlocksmbhdr(smb);
        !          1632:        return(SMB_SUCCESS);
        !          1633: }
        !          1634: 
        !          1635: /****************************************************************************/
        !          1636: /* Returns number of data blocks required to store "length" amount of data  */
        !          1637: /****************************************************************************/
        !          1638: ulong SMBCALL smb_datblocks(ulong length)
        !          1639: {
        !          1640:        ulong blocks;
        !          1641: 
        !          1642:        blocks=length/SDT_BLOCK_LEN;
        !          1643:        if(length%SDT_BLOCK_LEN)
        !          1644:                blocks++;
        !          1645:        return(blocks);
        !          1646: }
        !          1647: 
        !          1648: /****************************************************************************/
        !          1649: /* Returns number of header blocks required to store "length" size header   */
        !          1650: /****************************************************************************/
        !          1651: ulong SMBCALL smb_hdrblocks(ulong length)
        !          1652: {
        !          1653:        ulong blocks;
        !          1654: 
        !          1655:        blocks=length/SHD_BLOCK_LEN;
        !          1656:        if(length%SHD_BLOCK_LEN)
        !          1657:                blocks++;
        !          1658:        return(blocks);
        !          1659: }
        !          1660: 
        !          1661: /****************************************************************************/
        !          1662: /* Returns difference from specified timezone and UTC/GMT                                      */
        !          1663: /****************************************************************************/
        !          1664: int SMBCALL smb_tzutc(short zone)
        !          1665: {
        !          1666:        int tz;
        !          1667: 
        !          1668:        if(OTHER_ZONE(zone))
        !          1669:                return(zone);
        !          1670: 
        !          1671:        tz=zone&0xfff;
        !          1672:        if(zone&(WESTERN_ZONE|US_ZONE)) /* West of UTC? */
        !          1673:                return(-tz);
        !          1674:        return(tz);
        !          1675: }
        !          1676: 
        !          1677: /****************************************************************************/
        !          1678: /****************************************************************************/
        !          1679: int SMBCALL smb_updatethread(smb_t* smb, smbmsg_t* remsg, ulong newmsgnum)
        !          1680: {
        !          1681:        int                     retval=SMB_ERR_NOT_FOUND;
        !          1682:        ulong           nextmsgnum;
        !          1683:        smbmsg_t        nextmsg;
        !          1684: 
        !          1685:        if(!remsg->hdr.thread_first) {  /* New msg is first reply */
        !          1686:                remsg->hdr.thread_first=newmsgnum;
        !          1687:                if((retval=smb_lockmsghdr(smb,remsg))!=SMB_SUCCESS)
        !          1688:                        return(retval);
        !          1689:                retval=smb_putmsghdr(smb,remsg);
        !          1690:                smb_unlockmsghdr(smb,remsg);
        !          1691:                return(retval);
        !          1692:        }
        !          1693: 
        !          1694:        /* Search for last reply and extend chain */
        !          1695:        memset(&nextmsg,0,sizeof(nextmsg));
        !          1696:        nextmsgnum=remsg->hdr.thread_first;     /* start with first reply */
        !          1697: 
        !          1698:        while(1) {
        !          1699:                nextmsg.idx.offset=0;
        !          1700:                nextmsg.hdr.number=nextmsgnum;
        !          1701:                if(smb_getmsgidx(smb, &nextmsg)!=SMB_SUCCESS) /* invalid thread origin */
        !          1702:                        break;
        !          1703:                if(smb_lockmsghdr(smb,&nextmsg)!=SMB_SUCCESS)
        !          1704:                        break;
        !          1705:                if(smb_getmsghdr(smb, &nextmsg)!=SMB_SUCCESS) {
        !          1706:                        smb_unlockmsghdr(smb,&nextmsg); 
        !          1707:                        break;
        !          1708:                }
        !          1709:                if(nextmsg.hdr.thread_next && nextmsg.hdr.thread_next!=nextmsgnum) {
        !          1710:                        nextmsgnum=nextmsg.hdr.thread_next;
        !          1711:                        smb_unlockmsghdr(smb,&nextmsg);
        !          1712:                        smb_freemsgmem(&nextmsg);
        !          1713:                        continue; 
        !          1714:                }
        !          1715:                nextmsg.hdr.thread_next=newmsgnum;
        !          1716:                retval=smb_putmsghdr(smb,&nextmsg);
        !          1717:                smb_unlockmsghdr(smb,&nextmsg);
        !          1718:                smb_freemsgmem(&nextmsg);
        !          1719:                break; 
        !          1720:        }
        !          1721: 
        !          1722:        return(retval);
        !          1723: }
        !          1724: 
        !          1725: /* 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.