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