|
|
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 */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.