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