Annotation of sbbs/sbbs2/fido/smblib.c, revision 1.1.1.1

1.1       root        1: /* SMBLIB.C */
                      2: 
                      3: #include "smblib.h"
                      4: 
                      5: /****************************************************************************/
                      6: /* Open a message base of name 'smb_file'                                   */
                      7: /* If retry_time is 0, fast open method (no compatibility/validity check)      */
                      8: /* Opens files for READing messages or updating message indices only        */
                      9: /****************************************************************************/
                     10: int smb_open(int retry_time)
                     11: {
                     12:     int file;
                     13:     char str[128];
                     14:        smbhdr_t hdr;
                     15: 
                     16: shd_fp=sdt_fp=sid_fp=NULL;
                     17: sprintf(str,"%s.SHD",smb_file);
                     18: if((file=sopen(str,O_RDWR|O_CREAT|O_BINARY,SH_DENYNO,S_IWRITE|S_IREAD))==-1
                     19:        || (shd_fp=fdopen(file,"r+b"))==NULL) {
                     20:        if(file!=-1)
                     21:                close(file);
                     22:     return(2); }
                     23: 
                     24: if(retry_time && filelength(file)>=sizeof(smbhdr_t)) {
                     25:        setvbuf(shd_fp,shd_buf,_IONBF,SHD_BLOCK_LEN);
                     26:     if(smb_locksmbhdr(retry_time)) {
                     27:                smb_close();
                     28:         return(-1); }
                     29:        memset(&hdr,0,sizeof(smbhdr_t));
                     30:     fread(&hdr,sizeof(smbhdr_t),1,shd_fp);
                     31:     if(memcmp(hdr.id,"SMB\x1a",4)) {
                     32:                smb_close();
                     33:         return(-2); }
                     34:     if(hdr.version<0x110) {         /* Compatibility check */
                     35:                smb_close();
                     36:         return(-3); }
                     37:     smb_unlocksmbhdr();
                     38:        rewind(shd_fp); }
                     39: 
                     40: setvbuf(shd_fp,shd_buf,_IOFBF,SHD_BLOCK_LEN);
                     41: 
                     42: sprintf(str,"%s.SDT",smb_file);
                     43: if((file=sopen(str,O_RDWR|O_CREAT|O_BINARY,SH_DENYNO,S_IWRITE|S_IREAD))==-1
                     44:        || (sdt_fp=fdopen(file,"r+b"))==NULL) {
                     45:        if(file!=-1)
                     46:                close(file);
                     47:        smb_close();
                     48:        return(1); }
                     49: setvbuf(sdt_fp,NULL,_IOFBF,2*1024);
                     50: 
                     51: sprintf(str,"%s.SID",smb_file);
                     52: if((file=sopen(str,O_RDWR|O_CREAT|O_BINARY,SH_DENYNO,S_IWRITE|S_IREAD))==-1
                     53:        || (sid_fp=fdopen(file,"r+b"))==NULL) {
                     54:        if(file!=-1)
                     55:                close(file);
                     56:        smb_close();
                     57:        return(3); }
                     58: setvbuf(sid_fp,NULL,_IOFBF,2*1024);
                     59: 
                     60: return(0);
                     61: }
                     62: 
                     63: /****************************************************************************/
                     64: /* Closes the currently open message base                                                                      */
                     65: /****************************************************************************/
                     66: void smb_close(void)
                     67: {
                     68: if(shd_fp!=NULL) {
                     69:        smb_unlocksmbhdr();                     /* In case it's been locked */
                     70:        fclose(shd_fp); }
                     71: if(sid_fp!=NULL)
                     72:        fclose(sid_fp);
                     73: if(sdt_fp!=NULL)
                     74:        fclose(sdt_fp);
                     75: sid_fp=shd_fp=sdt_fp=NULL;
                     76: }
                     77: 
                     78: /****************************************************************************/
                     79: /* Opens the data block allocation table message base 'smb_file'            */
                     80: /* Retrys for retry_time number of seconds                                                                     */
                     81: /* Return 0 on success, non-zero otherwise                                                                     */
                     82: /****************************************************************************/
                     83: int smb_open_da(int retry_time)
                     84: {
                     85:     int file;
                     86:     char str[128];
                     87:        long start;
                     88: 
                     89: start=time(NULL);
                     90: sprintf(str,"%s.SDA",smb_file);
                     91: while(1) {
                     92:        if((file=sopen(str,O_RDWR|O_CREAT|O_BINARY,SH_DENYRW,S_IWRITE|S_IREAD))!=-1)
                     93:                break;
                     94:        if(errno!=EACCES)
                     95:                return(-1);
                     96:        if(time(NULL)-start>=retry_time)
                     97:                return(-2); }
                     98: if((sda_fp=fdopen(file,"r+b"))==NULL)
                     99:        return(-3);
                    100: setvbuf(sda_fp,NULL,_IOFBF,2*1024);
                    101: return(0);
                    102: }
                    103: 
                    104: /****************************************************************************/
                    105: /* Opens the header block allocation table for message base 'smb_file'      */
                    106: /* Retrys for retry_time number of seconds                                                                     */
                    107: /* Return 0 on success, non-zero otherwise                                                                     */
                    108: /****************************************************************************/
                    109: int smb_open_ha(int retry_time)
                    110: {
                    111:     int file;
                    112:     char str[128];
                    113:        long start;
                    114: 
                    115: start=time(NULL);
                    116: sprintf(str,"%s.SHA",smb_file);
                    117: while(1) {
                    118:        if((file=sopen(str,O_RDWR|O_CREAT|O_BINARY,SH_DENYRW,S_IWRITE|S_IREAD))!=-1)
                    119:                break;
                    120:        if(errno!=EACCES)
                    121:                return(-1);
                    122:        if(time(NULL)-start>=retry_time)
                    123:                return(-2); }
                    124: if((sha_fp=fdopen(file,"r+b"))==NULL)
                    125:        return(-3);
                    126: setvbuf(sha_fp,NULL,_IOFBF,2*1024);
                    127: return(0);
                    128: }
                    129: 
                    130: /****************************************************************************/
                    131: /* If the parameter 'push' is non-zero, this function stores the currently  */
                    132: /* open message base to the "virtual" smb stack. Up to SMB_STACK_LEN        */
                    133: /* message bases may be stored (defined in SMBDEFS.H).                                         */
                    134: /* The parameter 'op' is the operation to perform on the stack. Either      */
                    135: /* SMB_STACK_PUSH, SMB_STACK_POP, or SMB_STACK_XCHNG                                           */
                    136: /* If the operation is SMB_STACK_POP, this function restores a message base */
                    137: /* previously saved with a SMB_STACK_PUSH call to this same function.          */
                    138: /* If the operation is SMB_STACK_XCHNG, then the current message base is       */
                    139: /* exchanged with the message base on the top of the stack (most recently      */
                    140: /* pushed.                                                                                                                                     */
                    141: /* If the current message base is not open, the SMB_STACK_PUSH and                     */
                    142: /* SMB_STACK_XCHNG operations do nothing                                                                       */
                    143: /* Returns 0 on success, non-zero if stack full.                            */
                    144: /* If operation is SMB_STACK_POP or SMB_STACK_XCHNG, it always returns 0.      */
                    145: /****************************************************************************/
                    146: int smb_stack(int op)
                    147: {
                    148:        static char stack_file[SMB_STACK_LEN][128];
                    149:        static FILE *stack_sdt[SMB_STACK_LEN],
                    150:                                *stack_shd[SMB_STACK_LEN],
                    151:                                *stack_sid[SMB_STACK_LEN],
                    152:                                *stack_sda[SMB_STACK_LEN],
                    153:                                *stack_sha[SMB_STACK_LEN];
                    154:        static int      stack_idx;
                    155:        char            tmp_file[128];
                    156:        FILE            *tmp_sdt,
                    157:                                *tmp_shd,
                    158:                                *tmp_sid,
                    159:                                *tmp_sda,
                    160:                                *tmp_sha;
                    161: 
                    162: if(op==SMB_STACK_PUSH) {
                    163:        if(stack_idx>=SMB_STACK_LEN)
                    164:                return(1);
                    165:        if(shd_fp==NULL || sdt_fp==NULL || sid_fp==NULL) /* Msg base not open */
                    166:                return(0);
                    167:        memcpy(stack_file[stack_idx],smb_file,128);
                    168:        stack_sdt[stack_idx]=sdt_fp;
                    169:        stack_shd[stack_idx]=shd_fp;
                    170:        stack_sid[stack_idx]=sid_fp;
                    171:        stack_sda[stack_idx]=sda_fp;
                    172:        stack_sha[stack_idx]=sha_fp;
                    173:        stack_idx++;
                    174:        return(0); }
                    175: /* pop or xchng */
                    176: if(!stack_idx) /* Nothing on the stack, so do nothing */
                    177:        return(0);
                    178: if(op==SMB_STACK_XCHNG) {
                    179:        if(!shd_fp)
                    180:                return(0);
                    181:        memcpy(tmp_file,smb_file,128);
                    182:        tmp_sdt=sdt_fp;
                    183:        tmp_shd=shd_fp;
                    184:        tmp_sid=sid_fp;
                    185:        tmp_sda=sda_fp;
                    186:        tmp_sha=sha_fp; }
                    187: 
                    188: stack_idx--;
                    189: memcpy(smb_file,stack_file[stack_idx],128);
                    190: sdt_fp=stack_sdt[stack_idx];
                    191: shd_fp=stack_shd[stack_idx];
                    192: sid_fp=stack_sid[stack_idx];
                    193: sda_fp=stack_sda[stack_idx];
                    194: sha_fp=stack_sha[stack_idx];
                    195: if(op==SMB_STACK_XCHNG) {
                    196:        stack_idx++;
                    197:        memcpy(stack_file[stack_idx-1],tmp_file,128);
                    198:        stack_sdt[stack_idx-1]=tmp_sdt;
                    199:        stack_shd[stack_idx-1]=tmp_shd;
                    200:        stack_sid[stack_idx-1]=tmp_sid;
                    201:        stack_sda[stack_idx-1]=tmp_sda;
                    202:        stack_sha[stack_idx-1]=tmp_sha; }
                    203: return(0);
                    204: }
                    205: 
                    206: /****************************************************************************/
                    207: /* Truncates header file                                                                                                       */
                    208: /* Retrys for retry_time number of seconds                                                                     */
                    209: /* Return 0 on success, non-zero otherwise                                                                     */
                    210: /****************************************************************************/
                    211: int smb_trunchdr(int retry_time)
                    212: {
                    213:        long start;
                    214: 
                    215: start=time(NULL);
                    216: rewind(shd_fp);
                    217: while(1) {
                    218:        if(!chsize(fileno(shd_fp),0L))
                    219:                break;
                    220:        if(errno!=EACCES)
                    221:                return(-1);
                    222:        if(time(NULL)-start>=retry_time)                /* Time-out */
                    223:                return(-2); }
                    224: return(0);
                    225: }
                    226: 
                    227: /*********************************/
                    228: /* Message Base Header Functions */
                    229: /*********************************/
                    230: 
                    231: /****************************************************************************/
                    232: /* Attempts for retry_time number of seconds to lock the message base hdr      */
                    233: /****************************************************************************/
                    234: int smb_locksmbhdr(int retry_time)
                    235: {
                    236:        ulong start;
                    237: 
                    238: start=time(NULL);
                    239: while(1) {
                    240:        if(!lock(fileno(shd_fp),0L,sizeof(smbhdr_t)+sizeof(smbstatus_t)))
                    241:                return(0);
                    242:        if(time(NULL)-start>=retry_time)
                    243:                break;                                                  /* Incase we've already locked it */
                    244:        unlock(fileno(shd_fp),0L,sizeof(smbhdr_t)+sizeof(smbstatus_t)); }
                    245: return(-1);
                    246: }
                    247: 
                    248: /****************************************************************************/
                    249: /* Read the SMB header from the header file and place into "status"         */
                    250: /****************************************************************************/
                    251: int smb_getstatus(smbstatus_t *status)
                    252: {
                    253:     char    str[128];
                    254:        int     i;
                    255: 
                    256: setvbuf(shd_fp,shd_buf,_IONBF,SHD_BLOCK_LEN);
                    257: clearerr(shd_fp);
                    258: fseek(shd_fp,sizeof(smbhdr_t),SEEK_SET);
                    259: i=fread(status,1,sizeof(smbstatus_t),shd_fp);
                    260: setvbuf(shd_fp,shd_buf,_IOFBF,SHD_BLOCK_LEN);
                    261: if(i==sizeof(smbstatus_t))
                    262:        return(0);
                    263: return(1);
                    264: }
                    265: 
                    266: /****************************************************************************/
                    267: /* Writes message base header                                                                                          */
                    268: /****************************************************************************/
                    269: int smb_putstatus(smbstatus_t status)
                    270: {
                    271:        int i;
                    272: 
                    273: clearerr(shd_fp);
                    274: fseek(shd_fp,sizeof(smbhdr_t),SEEK_SET);
                    275: i=fwrite(&status,1,sizeof(smbstatus_t),shd_fp);
                    276: fflush(shd_fp);
                    277: if(i==sizeof(smbstatus_t))
                    278:        return(0);
                    279: return(1);
                    280: }
                    281: 
                    282: /****************************************************************************/
                    283: /* Unlocks previously locks message base header                                                        */
                    284: /****************************************************************************/
                    285: int smb_unlocksmbhdr()
                    286: {
                    287: return(unlock(fileno(shd_fp),0L,sizeof(smbhdr_t)+sizeof(smbstatus_t)));
                    288: }
                    289: 
                    290: /********************************/
                    291: /* Individual Message Functions */
                    292: /********************************/
                    293: 
                    294: /****************************************************************************/
                    295: /* Attempts for retry_time number of seconds to lock the header for 'msg'   */
                    296: /****************************************************************************/
                    297: int smb_lockmsghdr(smbmsg_t msg, int retry_time)
                    298: {
                    299:     ulong start;
                    300: 
                    301: start=time(NULL);
                    302: while(1) {
                    303:        if(!lock(fileno(shd_fp),msg.idx.offset,sizeof(msghdr_t)))
                    304:         return(0);
                    305:     if(time(NULL)-start>=retry_time)
                    306:                break;
                    307:        unlock(fileno(shd_fp),msg.idx.offset,sizeof(msghdr_t)); }
                    308: return(-1);
                    309: }
                    310: 
                    311: /****************************************************************************/
                    312: /* Fills msg->idx with message index based on msg->hdr.number                          */
                    313: /* OR if msg->hdr.number is 0, based on msg->offset (record offset).           */
                    314: /* if msg.hdr.number does not equal 0, then msg->offset is filled too.         */
                    315: /* Either msg->hdr.number or msg->offset must be initialized before            */
                    316: /* calling this function                                                                                                       */
                    317: /* Returns 1 if message number wasn't found, 0 if it was                    */
                    318: /****************************************************************************/
                    319: int smb_getmsgidx(smbmsg_t *msg)
                    320: {
                    321:        idxrec_t idx;
                    322:        ulong    l,length,total,bot,top;
                    323: 
                    324: clearerr(sid_fp);
                    325: if(!msg->hdr.number) {
                    326:        fseek(sid_fp,msg->offset*sizeof(idxrec_t),SEEK_SET);
                    327:        if(!fread(&msg->idx,sizeof(idxrec_t),1,sid_fp))
                    328:                return(1);
                    329:        return(0); }
                    330: 
                    331: length=filelength(fileno(sid_fp));
                    332: if(!length)
                    333:        return(1);
                    334: total=length/sizeof(idxrec_t);
                    335: if(!total)
                    336:        return(1);
                    337: 
                    338: bot=0;
                    339: top=total;
                    340: l=total/2; /* Start at middle index */
                    341: while(1) {
                    342:        fseek(sid_fp,l*sizeof(idxrec_t),SEEK_SET);
                    343:        if(!fread(&idx,sizeof(idxrec_t),1,sid_fp))
                    344:                return(1);
                    345:        if(bot==top-1 && idx.number!=msg->hdr.number)
                    346:         return(1);
                    347:        if(idx.number>msg->hdr.number) {
                    348:                top=l;
                    349:                l=bot+((top-bot)/2);
                    350:                continue; }
                    351:        if(idx.number<msg->hdr.number) {
                    352:                bot=l;
                    353:                l=top-((top-bot)/2);
                    354:                continue; }
                    355:        break; }
                    356: msg->idx=idx;
                    357: msg->offset=l;
                    358: return(0);
                    359: }
                    360: 
                    361: /****************************************************************************/
                    362: /* Reads the last index record in the open message base                                        */
                    363: /****************************************************************************/
                    364: int smb_getlastidx(idxrec_t *idx)
                    365: {
                    366:        long length;
                    367: 
                    368: clearerr(sid_fp);
                    369: length=filelength(fileno(sid_fp));
                    370: if(length<sizeof(idxrec_t))
                    371:        return(-1);
                    372: fseek(sid_fp,length-sizeof(idxrec_t),SEEK_SET);
                    373: if(!fread(idx,sizeof(idxrec_t),1,sid_fp))
                    374:        return(-2);
                    375: return(0);
                    376: }
                    377: 
                    378: /****************************************************************************/
                    379: /* Figures out the total length of the header record for 'msg'              */
                    380: /* Returns length                                                                                                                      */
                    381: /****************************************************************************/
                    382: uint smb_getmsghdrlen(smbmsg_t msg)
                    383: {
                    384:        int i;
                    385: 
                    386: /* fixed portion */
                    387: msg.hdr.length=sizeof(msghdr_t);
                    388: /* data fields */
                    389: msg.hdr.length+=msg.hdr.total_dfields*sizeof(dfield_t);
                    390: /* header fields */
                    391: for(i=0;i<msg.total_hfields;i++) {
                    392:        msg.hdr.length+=sizeof(hfield_t);
                    393:        msg.hdr.length+=msg.hfield[i].length; }
                    394: return(msg.hdr.length);
                    395: }
                    396: 
                    397: /****************************************************************************/
                    398: /* Figures out the total length of the data buffer for 'msg'                */
                    399: /* Returns length                                                                                                                      */
                    400: /****************************************************************************/
                    401: ulong smb_getmsgdatlen(smbmsg_t msg)
                    402: {
                    403:        int i;
                    404:        ulong length=0L;
                    405: 
                    406: for(i=0;i<msg.hdr.total_dfields;i++)
                    407:        length+=msg.dfield[i].length;
                    408: return(length);
                    409: }
                    410: 
                    411: /****************************************************************************/
                    412: /* Read header information into 'msg' structure                             */
                    413: /* msg->idx.offset must be set before calling this function                            */
                    414: /* Must call smb_freemsgmem() to free memory allocated for var len strs        */
                    415: /* Returns 0 on success, non-zero if error                                                                     */
                    416: /****************************************************************************/
                    417: int smb_getmsghdr(smbmsg_t *msg)
                    418: {
                    419:        ushort  i;
                    420:        ulong   l,offset;
                    421:        idxrec_t idx;
                    422: 
                    423: rewind(shd_fp);
                    424: fseek(shd_fp,msg->idx.offset,SEEK_SET);
                    425: idx=msg->idx;
                    426: offset=msg->offset;
                    427: memset(msg,0,sizeof(smbmsg_t));
                    428: msg->idx=idx;
                    429: msg->offset=offset;
                    430: if(!fread(&msg->hdr,sizeof(msghdr_t),1,shd_fp))
                    431:        return(-1);
                    432: if(memcmp(msg->hdr.id,"SHD\x1a",4))
                    433:        return(-2);
                    434: if(msg->hdr.version<0x110)
                    435:        return(-9);
                    436: l=sizeof(msghdr_t);
                    437: if(msg->hdr.total_dfields && (msg->dfield
                    438:        =(dfield_t *)MALLOC(sizeof(dfield_t)*msg->hdr.total_dfields))==NULL) {
                    439:        smb_freemsgmem(*msg);
                    440:        return(-3); }
                    441: i=0;
                    442: while(i<msg->hdr.total_dfields && l<msg->hdr.length) {
                    443:        if(!fread(&msg->dfield[i],sizeof(dfield_t),1,shd_fp)) {
                    444:                smb_freemsgmem(*msg);
                    445:                return(-4); }
                    446:        i++;
                    447:        l+=sizeof(dfield_t); }
                    448: if(i<msg->hdr.total_dfields) {
                    449:        smb_freemsgmem(*msg);
                    450:        return(-8); }
                    451: 
                    452: while(l<msg->hdr.length) {
                    453:        i=msg->total_hfields;
                    454:        if((msg->hfield_dat=(void **)REALLOC(msg->hfield_dat,sizeof(void *)*(i+1)))
                    455:                ==NULL) {
                    456:                smb_freemsgmem(*msg);
                    457:                return(-3); }
                    458:        if((msg->hfield=(hfield_t *)REALLOC(msg->hfield
                    459:                ,sizeof(hfield_t)*(i+1)))==NULL) {
                    460:                smb_freemsgmem(*msg);
                    461:                return(-3); }
                    462:        msg->total_hfields++;
                    463:        if(!fread(&msg->hfield[i],sizeof(hfield_t),1,shd_fp)) {
                    464:                smb_freemsgmem(*msg);
                    465:                return(-5); }
                    466:        l+=sizeof(hfield_t);
                    467:        if((msg->hfield_dat[i]=(char *)MALLOC(msg->hfield[i].length+1))
                    468:                ==NULL) {                       /* Allocate 1 extra for NULL terminator */
                    469:                smb_freemsgmem(*msg);  /* or 0 length field */
                    470:                return(-3); }
                    471:        memset(msg->hfield_dat[i],0,msg->hfield[i].length+1);  /* init to NULL */
                    472:        if(msg->hfield[i].length
                    473:                && !fread(msg->hfield_dat[i],msg->hfield[i].length,1,shd_fp)) {
                    474:                smb_freemsgmem(*msg);
                    475:                return(-6); }
                    476: 
                    477:        switch(msg->hfield[i].type) {   /* convenience variables */
                    478:                case SENDER:
                    479:                        if(!msg->from) {
                    480:                                msg->from=msg->hfield_dat[i];
                    481:                                break; }
                    482:                case FORWARDED:         /* fall through */
                    483:                        msg->forwarded=1;
                    484:                        break;
                    485:                case SENDERAGENT:
                    486:                        if(!msg->forwarded)
                    487:                                msg->from_agent=*(ushort *)msg->hfield_dat[i];
                    488:             break;
                    489:                case SENDEREXT:
                    490:                        if(!msg->forwarded)
                    491:                                msg->from_ext=msg->hfield_dat[i];
                    492:                        break;
                    493:                case SENDERNETTYPE:
                    494:                        if(!msg->forwarded)
                    495:                                msg->from_net.type=*(ushort *)msg->hfield_dat[i];
                    496:             break;
                    497:                case SENDERNETADDR:
                    498:                        if(!msg->forwarded)
                    499:                                msg->from_net.addr=msg->hfield_dat[i];
                    500:             break;
                    501:                case REPLYTO:
                    502:                        msg->replyto=msg->hfield_dat[i];
                    503:             break;
                    504:                case REPLYTOEXT:
                    505:                        msg->replyto_ext=msg->hfield_dat[i];
                    506:                        break;
                    507:                case REPLYTOAGENT:
                    508:                        msg->replyto_agent=*(ushort *)msg->hfield_dat[i];
                    509:             break;
                    510:                case REPLYTONETTYPE:
                    511:                        msg->replyto_net.type=*(ushort *)msg->hfield_dat[i];
                    512:             break;
                    513:                case REPLYTONETADDR:
                    514:                        msg->replyto_net.addr=msg->hfield_dat[i];
                    515:             break;
                    516:                case RECIPIENT:
                    517:                        msg->to=msg->hfield_dat[i];
                    518:             break;
                    519:                case RECIPIENTEXT:
                    520:                        msg->to_ext=msg->hfield_dat[i];
                    521:                        break;
                    522:                case RECIPIENTAGENT:
                    523:                        msg->to_agent=*(ushort *)msg->hfield_dat[i];
                    524:             break;
                    525:                case RECIPIENTNETTYPE:
                    526:                        msg->to_net.type=*(ushort *)msg->hfield_dat[i];
                    527:             break;
                    528:                case RECIPIENTNETADDR:
                    529:                        msg->to_net.addr=msg->hfield_dat[i];
                    530:             break;
                    531:                case SUBJECT:
                    532:                        msg->subj=msg->hfield_dat[i];
                    533:                        break; }
                    534:        l+=msg->hfield[i].length; }
                    535: 
                    536: if(!msg->from || !msg->to || !msg->subj) {
                    537:        smb_freemsgmem(*msg);
                    538:        return(-7); }
                    539: return(0);
                    540: }
                    541: 
                    542: /****************************************************************************/
                    543: /* Frees memory allocated for 'msg'                                         */
                    544: /****************************************************************************/
                    545: void smb_freemsgmem(smbmsg_t msg)
                    546: {
                    547:        ushort  i;
                    548: 
                    549: if(msg.dfield)
                    550:        FREE(msg.dfield);
                    551: for(i=0;i<msg.total_hfields;i++)
                    552:        if(msg.hfield_dat[i])
                    553:                FREE(msg.hfield_dat[i]);
                    554: if(msg.hfield)
                    555:        FREE(msg.hfield);
                    556: if(msg.hfield_dat)
                    557:        FREE(msg.hfield_dat);
                    558: }
                    559: 
                    560: /****************************************************************************/
                    561: /* Unlocks header for 'msg'                                                 */
                    562: /****************************************************************************/
                    563: int smb_unlockmsghdr(smbmsg_t msg)
                    564: {
                    565: return(unlock(fileno(shd_fp),msg.idx.offset,sizeof(msghdr_t)));
                    566: }
                    567: 
                    568: 
                    569: /****************************************************************************/
                    570: /* Adds a header field to the 'msg' structure (in memory only)              */
                    571: /****************************************************************************/
                    572: int smb_hfield(smbmsg_t *msg, ushort type, ushort length, void *data)
                    573: {
                    574:        int i;
                    575: 
                    576: i=msg->total_hfields;
                    577: if((msg->hfield=(hfield_t *)REALLOC(msg->hfield,sizeof(hfield_t)*(i+1)))
                    578:        ==NULL)
                    579:        return(1);
                    580: if((msg->hfield_dat=(void **)REALLOC(msg->hfield_dat,sizeof(void *)*(i+1)))
                    581:        ==NULL)
                    582:        return(2);
                    583: msg->total_hfields++;
                    584: msg->hfield[i].type=type;
                    585: msg->hfield[i].length=length;
                    586: if(length) {
                    587:        if((msg->hfield_dat[i]=(void *)MALLOC(length))==NULL)
                    588:                return(4);
                    589:        memcpy(msg->hfield_dat[i],data,length); }
                    590: else
                    591:        msg->hfield_dat[i]=NULL;
                    592: return(0);
                    593: }
                    594: 
                    595: /****************************************************************************/
                    596: /* Adds a data field to the 'msg' structure (in memory only)                */
                    597: /* Automatically figures out the offset into the data buffer from existing     */
                    598: /* dfield lengths                                                                                                                      */
                    599: /****************************************************************************/
                    600: int smb_dfield(smbmsg_t *msg, ushort type, ulong length)
                    601: {
                    602:        int i,j;
                    603: 
                    604: i=msg->hdr.total_dfields;
                    605: if((msg->dfield=(dfield_t *)REALLOC(msg->dfield,sizeof(dfield_t)*(i+1)))
                    606:        ==NULL)
                    607:        return(1);
                    608: msg->hdr.total_dfields++;
                    609: msg->dfield[i].type=type;
                    610: msg->dfield[i].length=length;
                    611: for(j=msg->dfield[i].offset=0;j<i;j++)
                    612:        msg->dfield[i].offset+=msg->dfield[j].length;
                    613: return(0);
                    614: }
                    615: 
                    616: /****************************************************************************/
                    617: /* Checks CRC history file for duplicate crc. If found, returns 1.                     */
                    618: /* If no dupe, adds to CRC history and returns 0, or negative if error.        */
                    619: /****************************************************************************/
                    620: int smb_addcrc(ulong max_crcs, ulong crc, int retry_time)
                    621: {
                    622:        char    str[128];
                    623:        int     file;
                    624:        long    length;
                    625:        ulong   l,*buf;
                    626:        time_t  start;
                    627: 
                    628: if(!max_crcs)
                    629:        return(0);
                    630: start=time(NULL);
                    631: sprintf(str,"%s.SCH",smb_file);
                    632: while(1) {
                    633:        if((file=sopen(str,O_RDWR|O_CREAT|O_BINARY,SH_DENYRW,S_IWRITE|S_IREAD))!=-1)
                    634:                break;
                    635:        if(errno!=EACCES)
                    636:                return(-1);
                    637:        if(time(NULL)-start>=retry_time)
                    638:         return(-2); }
                    639: length=filelength(file);
                    640: if(length<0L) {
                    641:        close(file);
                    642:        return(-4); }
                    643: if((buf=(ulong *)MALLOC(max_crcs*4))==NULL) {
                    644:        close(file);
                    645:        return(-3); }
                    646: if(length>=max_crcs*4) {                       /* Reached or exceeds max crcs */
                    647:        read(file,buf,max_crcs*4);
                    648:        for(l=0;l<max_crcs;l++)
                    649:                if(crc==buf[l])
                    650:                        break;
                    651:        if(l<max_crcs) {                                /* Dupe CRC found */
                    652:                close(file);
                    653:                FREE(buf);
                    654:                return(1); }
                    655:        chsize(file,0L);                                /* truncate it */
                    656:        lseek(file,0L,SEEK_SET);
                    657:        write(file,buf+4,(max_crcs-1)*4); }
                    658: 
                    659: else if(length/4) {                                            /* Less than max crcs */
                    660:        read(file,buf,length);
                    661:        for(l=0;l<length/4;l++)
                    662:                if(crc==buf[l])
                    663:                        break;
                    664:        if(l<length/4) {                                        /* Dupe CRC found */
                    665:                close(file);
                    666:                FREE(buf);
                    667:                return(1); } }
                    668: 
                    669: lseek(file,0L,SEEK_END);
                    670: write(file,&crc,4);                       /* Write to the end */
                    671: FREE(buf);
                    672: close(file);
                    673: return(0);
                    674: }
                    675: 
                    676: 
                    677: /****************************************************************************/
                    678: /* Creates a new message header record in the header file.                                     */
                    679: /* If storage is SMB_SELFPACK, self-packing conservative allocation is used */
                    680: /* If storage is SMB_FASTALLOC, fast allocation is used                                        */
                    681: /* If storage is SMB_HYPERALLOC, no allocation tables are used (fastest)       */
                    682: /****************************************************************************/
                    683: int smb_addmsghdr(smbmsg_t *msg, smbstatus_t *status, int storage
                    684:        ,int retry_time)
                    685: {
                    686:        int i;
                    687:        long l;
                    688: 
                    689: if(smb_locksmbhdr(retry_time))
                    690:     return(1);
                    691: if(smb_getstatus(status))
                    692:     return(2);
                    693: 
                    694: if(storage!=SMB_HYPERALLOC && (i=smb_open_ha(retry_time))!=0)
                    695:     return(i);
                    696: 
                    697: msg->hdr.length=smb_getmsghdrlen(*msg);
                    698: if(storage==SMB_HYPERALLOC)
                    699:        l=smb_hallochdr(status->header_offset);
                    700: else if(storage==SMB_FASTALLOC)
                    701:     l=smb_fallochdr(msg->hdr.length);
                    702: else
                    703:     l=smb_allochdr(msg->hdr.length);
                    704: if(l==-1L) {
                    705:        smb_unlocksmbhdr();
                    706:        fclose(sha_fp);
                    707:        return(-1); }
                    708: 
                    709: status->last_msg++;
                    710: msg->idx.number=msg->hdr.number=status->last_msg;
                    711: msg->idx.offset=status->header_offset+l;
                    712: msg->idx.time=msg->hdr.when_imported.time;
                    713: msg->idx.attr=msg->hdr.attr;
                    714: msg->offset=status->total_msgs;
                    715: status->total_msgs++;
                    716: smb_putstatus(*status);
                    717: 
                    718: if(storage!=SMB_HYPERALLOC)
                    719:        fclose(sha_fp);
                    720: i=smb_putmsg(*msg);
                    721: smb_unlocksmbhdr();
                    722: return(i);
                    723: }
                    724: 
                    725: /****************************************************************************/
                    726: /* Writes both header and index information for msg 'msg'                   */
                    727: /****************************************************************************/
                    728: int smb_putmsg(smbmsg_t msg)
                    729: {
                    730:        int i;
                    731: 
                    732: i=smb_putmsghdr(msg);
                    733: if(i)
                    734:        return(i);
                    735: return(smb_putmsgidx(msg));
                    736: }
                    737: 
                    738: /****************************************************************************/
                    739: /* Writes index information for 'msg'                                       */
                    740: /* msg.idx                                                                                                                                     */
                    741: /* and msg.offset must be set prior to calling to this function             */
                    742: /* Returns 0 if everything ok                                               */
                    743: /****************************************************************************/
                    744: int smb_putmsgidx(smbmsg_t msg)
                    745: {
                    746: 
                    747: clearerr(sid_fp);
                    748: fseek(sid_fp,msg.offset*sizeof(idxrec_t),SEEK_SET);
                    749: if(!fwrite(&msg.idx,sizeof(idxrec_t),1,sid_fp))
                    750:        return(1);
                    751: fflush(sid_fp);
                    752: return(0);
                    753: }
                    754: 
                    755: /****************************************************************************/
                    756: /* Writes header information for 'msg'                                      */
                    757: /* msg.hdr.length                                                           */
                    758: /* msg.idx.offset                                                           */
                    759: /* and msg.offset must be set prior to calling to this function             */
                    760: /* Returns 0 if everything ok                                               */
                    761: /****************************************************************************/
                    762: int smb_putmsghdr(smbmsg_t msg)
                    763: {
                    764:        ushort  i;
                    765:        ulong   l;
                    766: 
                    767: clearerr(shd_fp);
                    768: if(fseek(shd_fp,msg.idx.offset,SEEK_SET))
                    769:        return(-1);
                    770: 
                    771: /************************************************/
                    772: /* Write the fixed portion of the header record */
                    773: /************************************************/
                    774: if(!fwrite(&msg.hdr,sizeof(msghdr_t),1,shd_fp))
                    775:        return(-2);
                    776: 
                    777: /************************************************/
                    778: /* Write the data fields (each is fixed length) */
                    779: /************************************************/
                    780: for(i=0;i<msg.hdr.total_dfields;i++)
                    781:        if(!fwrite(&msg.dfield[i],sizeof(dfield_t),1,shd_fp))
                    782:                return(-3);
                    783: 
                    784: /*******************************************/
                    785: /* Write the variable length header fields */
                    786: /*******************************************/
                    787: for(i=0;i<msg.total_hfields;i++) {
                    788:        if(!fwrite(&msg.hfield[i],sizeof(hfield_t),1,shd_fp))
                    789:                return(-4);
                    790:        if(msg.hfield[i].length                                         /* more then 0 bytes long */
                    791:                && !fwrite(msg.hfield_dat[i],msg.hfield[i].length,1,shd_fp))
                    792:                return(-5); }
                    793: 
                    794: l=smb_getmsghdrlen(msg);
                    795: while(l%SHD_BLOCK_LEN) {
                    796:        if(fputc(0,shd_fp)==EOF)
                    797:                return(-6);                        /* pad block with NULL */
                    798:        l++; }
                    799: fflush(shd_fp);
                    800: return(0);
                    801: }
                    802: 
                    803: /****************************************************************************/
                    804: /* Creates a sub-board's initial header file                                */
                    805: /* Truncates and deletes other associated SMB files                                            */
                    806: /****************************************************************************/
                    807: int smb_create(ulong max_crcs, ulong max_msgs, ushort max_age, ushort attr
                    808:        ,int retry_time)
                    809: {
                    810:     char        str[128];
                    811:        smbhdr_t        hdr;
                    812:        smbstatus_t status;
                    813: 
                    814: if(filelength(fileno(shd_fp))>=sizeof(smbhdr_t)+sizeof(smbstatus_t)
                    815:        && smb_locksmbhdr(retry_time))  /* header exists, so lock it */
                    816:        return(1);
                    817: memset(&hdr,0,sizeof(smbhdr_t));
                    818: memset(&status,0,sizeof(smbstatus_t));
                    819: memcpy(hdr.id,"SMB\x1a",4);     /* <S> <M> <B> <^Z> */
                    820: hdr.version=SMB_VERSION;
                    821: hdr.length=sizeof(smbhdr_t)+sizeof(smbstatus_t);
                    822: status.last_msg=status.total_msgs=0;
                    823: status.header_offset=sizeof(smbhdr_t)+sizeof(smbstatus_t);
                    824: status.max_crcs=max_crcs;
                    825: status.max_msgs=max_msgs;
                    826: status.max_age=max_age;
                    827: status.attr=attr;
                    828: rewind(shd_fp);
                    829: fwrite(&hdr,1,sizeof(smbhdr_t),shd_fp);
                    830: fwrite(&status,1,sizeof(smbstatus_t),shd_fp);
                    831: rewind(shd_fp);
                    832: chsize(fileno(shd_fp),sizeof(smbhdr_t)+sizeof(smbstatus_t));
                    833: fflush(shd_fp);
                    834: 
                    835: rewind(sdt_fp);
                    836: chsize(fileno(sdt_fp),0L);
                    837: rewind(sid_fp);
                    838: chsize(fileno(sid_fp),0L);
                    839: 
                    840: sprintf(str,"%s.SDA",smb_file);
                    841: remove(str);                                           /* if it exists, delete it */
                    842: sprintf(str,"%s.SHA",smb_file);
                    843: remove(str);                        /* if it exists, delete it */
                    844: sprintf(str,"%s.SCH",smb_file);
                    845: remove(str);
                    846: smb_unlocksmbhdr();
                    847: return(0);
                    848: }
                    849: 
                    850: /****************************************************************************/
                    851: /* Returns number of data blocks required to store "length" amount of data  */
                    852: /****************************************************************************/
                    853: ulong smb_datblocks(ulong length)
                    854: {
                    855:        ulong blocks;
                    856: 
                    857: blocks=length/SDT_BLOCK_LEN;
                    858: if(length%SDT_BLOCK_LEN)
                    859:        blocks++;
                    860: return(blocks);
                    861: }
                    862: 
                    863: /****************************************************************************/
                    864: /* Returns number of header blocks required to store "length" size header   */
                    865: /****************************************************************************/
                    866: ulong smb_hdrblocks(ulong length)
                    867: {
                    868:        ulong blocks;
                    869: 
                    870: blocks=length/SHD_BLOCK_LEN;
                    871: if(length%SHD_BLOCK_LEN)
                    872:        blocks++;
                    873: return(blocks);
                    874: }
                    875: 
                    876: /****************************************************************************/
                    877: /* Finds unused space in data file based on block allocation table and         */
                    878: /* marks space as used in allocation table.                                 */
                    879: /* File must be opened read/write DENY ALL                                                                     */
                    880: /* Returns offset to beginning of data (in bytes, not blocks)                          */
                    881: /* Assumes smb_open_da() has been called                                                                       */
                    882: /* fclose(sda_fp) should be called after                                                                       */
                    883: /* Returns negative on error                                                                                           */
                    884: /****************************************************************************/
                    885: long smb_allocdat(ulong length, ushort headers)
                    886: {
                    887:     ushort  i,j;
                    888:        ulong   l,blocks,offset=0L;
                    889: 
                    890: blocks=smb_datblocks(length);
                    891: j=0;   /* j is consecutive unused block counter */
                    892: fflush(sda_fp);
                    893: rewind(sda_fp);
                    894: while(!feof(sda_fp)) {
                    895:        if(!fread(&i,2,1,sda_fp))
                    896:         break;
                    897:        offset+=SDT_BLOCK_LEN;
                    898:     if(!i) j++;
                    899:     else   j=0;
                    900:        if(j==blocks) {
                    901:                offset-=(blocks*SDT_BLOCK_LEN);
                    902:         break; } }
                    903: clearerr(sda_fp);
                    904: fseek(sda_fp,(offset/SDT_BLOCK_LEN)*2L,SEEK_SET);
                    905: for(l=0;l<blocks;l++)
                    906:        if(!fwrite(&headers,2,1,sda_fp))
                    907:                return(-1);
                    908: fflush(sda_fp);
                    909: return(offset);
                    910: }
                    911: 
                    912: /****************************************************************************/
                    913: /* Allocates space for data, but doesn't search for unused blocks           */
                    914: /* Returns negative on error                                                                                           */
                    915: /****************************************************************************/
                    916: long smb_fallocdat(ulong length, ushort headers)
                    917: {
                    918:        ulong   l,blocks,offset;
                    919: 
                    920: fflush(sda_fp);
                    921: clearerr(sda_fp);
                    922: blocks=smb_datblocks(length);
                    923: fseek(sda_fp,0L,SEEK_END);
                    924: offset=(ftell(sda_fp)/2L)*SDT_BLOCK_LEN;
                    925: for(l=0;l<blocks;l++)
                    926:        if(!fwrite(&headers,2,1,sda_fp))
                    927:         break;
                    928: fflush(sda_fp);
                    929: if(l<blocks)
                    930:        return(-1L);
                    931: return(offset);
                    932: }
                    933: 
                    934: /****************************************************************************/
                    935: /* De-allocates space for data                                                                                         */
                    936: /* Returns non-zero on error                                                                                           */
                    937: /****************************************************************************/
                    938: int smb_freemsgdat(ulong offset, ulong length, ushort headers)
                    939: {
                    940:        ushort  i;
                    941:        ulong   l,blocks;
                    942: 
                    943: blocks=smb_datblocks(length);
                    944: 
                    945: clearerr(sda_fp);
                    946: for(l=0;l<blocks;l++) {
                    947:        if(fseek(sda_fp,((offset/SDT_BLOCK_LEN)+l)*2L,SEEK_SET))
                    948:                return(1);
                    949:        if(!fread(&i,2,1,sda_fp))
                    950:                return(2);
                    951:        if(headers>i)
                    952:                i=0;                    /* don't want to go negative */
                    953:        else
                    954:                i-=headers;
                    955:        if(fseek(sda_fp,-2L,SEEK_CUR))
                    956:                return(3);
                    957:        if(!fwrite(&i,2,1,sda_fp))
                    958:                return(4); }
                    959: fflush(sda_fp);
                    960: return(0);
                    961: }
                    962: 
                    963: /****************************************************************************/
                    964: /* Adds to data allocation records for blocks starting at 'offset'          */
                    965: /* Returns non-zero on error                                                                                           */
                    966: /****************************************************************************/
                    967: int smb_incdat(ulong offset, ulong length, ushort headers)
                    968: {
                    969:        ushort  i;
                    970:        ulong   l,blocks;
                    971: 
                    972: clearerr(sda_fp);
                    973: blocks=smb_datblocks(length);
                    974: for(l=0;l<blocks;l++) {
                    975:        fseek(sda_fp,((offset/SDT_BLOCK_LEN)+l)*2L,SEEK_SET);
                    976:        if(!fread(&i,2,1,sda_fp))
                    977:                return(1);
                    978:        i+=headers;
                    979:        fseek(sda_fp,-2L,SEEK_CUR);
                    980:        if(!fwrite(&i,2,1,sda_fp))
                    981:                return(2); }
                    982: fflush(sda_fp);
                    983: return(0);
                    984: }
                    985: 
                    986: /****************************************************************************/
                    987: /* De-allocates blocks for header record                                                                       */
                    988: /* Returns non-zero on error                                                                                           */
                    989: /****************************************************************************/
                    990: int smb_freemsghdr(ulong offset, ulong length)
                    991: {
                    992:        uchar   c=0;
                    993:        ulong   l,blocks;
                    994: 
                    995: clearerr(sha_fp);
                    996: blocks=smb_hdrblocks(length);
                    997: fseek(sha_fp,offset/SHD_BLOCK_LEN,SEEK_SET);
                    998: for(l=0;l<blocks;l++)
                    999:        if(!fwrite(&c,1,1,sha_fp))
                   1000:                return(1);
                   1001: fflush(sha_fp);
                   1002: return(0);
                   1003: }
                   1004: 
                   1005: /****************************************************************************/
                   1006: /* Frees all allocated header and data blocks for 'msg'                     */
                   1007: /****************************************************************************/
                   1008: int smb_freemsg(smbmsg_t msg, smbstatus_t status)
                   1009: {
                   1010:        int     i;
                   1011:        ushort  x;
                   1012: 
                   1013: if(status.attr&SMB_HYPERALLOC) /* Nothing to do */
                   1014:        return(0);
                   1015: 
                   1016: for(x=0;x<msg.hdr.total_dfields;x++) {
                   1017:        if((i=smb_freemsgdat(msg.hdr.offset+msg.dfield[x].offset
                   1018:                ,msg.dfield[x].length,1))!=0)
                   1019:                return(i); }
                   1020: return(smb_freemsghdr(msg.idx.offset-status.header_offset,msg.hdr.length));
                   1021: }
                   1022: 
                   1023: /****************************************************************************/
                   1024: /* Finds unused space in header file based on block allocation table and       */
                   1025: /* marks space as used in allocation table.                                 */
                   1026: /* File must be opened read/write DENY ALL                                                                     */
                   1027: /* Returns offset to beginning of header (in bytes, not blocks)                        */
                   1028: /* Assumes smb_open_ha() has been called                                                                       */
                   1029: /* fclose(sha_fp) should be called after                                                                       */
                   1030: /* Returns -1L on error                                                                                                        */
                   1031: /****************************************************************************/
                   1032: long smb_allochdr(ulong length)
                   1033: {
                   1034:        uchar   c;
                   1035:        ushort  i;
                   1036:        ulong   l,blocks,offset=0;
                   1037: 
                   1038: blocks=smb_hdrblocks(length);
                   1039: i=0;   /* i is consecutive unused block counter */
                   1040: fflush(sha_fp);
                   1041: rewind(sha_fp);
                   1042: while(!feof(sha_fp)) {
                   1043:        if(!fread(&c,1,1,sha_fp))
                   1044:         break;
                   1045:        offset+=SHD_BLOCK_LEN;
                   1046:        if(!c) i++;
                   1047:        else   i=0;
                   1048:        if(i==blocks) {
                   1049:                offset-=(blocks*SHD_BLOCK_LEN);
                   1050:         break; } }
                   1051: clearerr(sha_fp);
                   1052: fseek(sha_fp,offset/SHD_BLOCK_LEN,SEEK_SET);
                   1053: c=1;
                   1054: for(l=0;l<blocks;l++)
                   1055:        if(!fwrite(&c,1,1,sha_fp))
                   1056:                return(-1L);
                   1057: fflush(sha_fp);
                   1058: return(offset);
                   1059: }
                   1060: 
                   1061: /****************************************************************************/
                   1062: /* Allocates space for index, but doesn't search for unused blocks          */
                   1063: /* Returns -1L on error                                                                                                        */
                   1064: /****************************************************************************/
                   1065: long smb_fallochdr(ulong length)
                   1066: {
                   1067:        uchar   c=1;
                   1068:        ulong   l,blocks,offset;
                   1069: 
                   1070: blocks=smb_hdrblocks(length);
                   1071: fflush(sha_fp);
                   1072: clearerr(sha_fp);
                   1073: fseek(sha_fp,0L,SEEK_END);
                   1074: offset=ftell(sha_fp)*SHD_BLOCK_LEN;
                   1075: for(l=0;l<blocks;l++)
                   1076:        if(!fwrite(&c,1,1,sha_fp))
                   1077:                return(-1L);
                   1078: fflush(sha_fp);
                   1079: return(offset);
                   1080: }
                   1081: 
                   1082: /************************************************************************/
                   1083: /* Allocate header blocks using Hyper Allocation                                               */
                   1084: /* this function should be most likely not be called from anywhere but */
                   1085: /* smb_addmsghdr()                                                                                                             */
                   1086: /************************************************************************/
                   1087: long smb_hallochdr(ulong header_offset)
                   1088: {
                   1089:        long l;
                   1090: 
                   1091: fflush(shd_fp);
                   1092: fseek(shd_fp,0L,SEEK_END);
                   1093: l=ftell(shd_fp);
                   1094: if(l<header_offset)                                    /* Header file truncated?!? */
                   1095:        return(header_offset);
                   1096: while((l-header_offset)%SHD_BLOCK_LEN) /* Make sure even block boundry */
                   1097:        l++;
                   1098: return(l-header_offset);
                   1099: }
                   1100: 
                   1101: /************************************************************************/
                   1102: /* Allocate data blocks using Hyper Allocation                                                 */
                   1103: /* smb_locksmbhdr() should be called before this function and not              */
                   1104: /* unlocked until all data fields for this message have been written   */
                   1105: /* to the SDT file                                                                                                             */
                   1106: /************************************************************************/
                   1107: long smb_hallocdat()
                   1108: {
                   1109:        long l;
                   1110: 
                   1111: fflush(sdt_fp);
                   1112: fseek(sdt_fp,0L,SEEK_END);
                   1113: l=ftell(sdt_fp);
                   1114: if(l<=0)
                   1115:        return(l);
                   1116: while(l%SDT_BLOCK_LEN)                                 /* Make sure even block boundry */
                   1117:        l++;
                   1118: return(l);
                   1119: }
                   1120: 
                   1121: /* 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.