|
|
1.1 ! root 1: /* smballoc.c */ ! 2: ! 3: /* Synchronet message base (SMB) alloc/free routines */ ! 4: ! 5: /* $Id: smballoc.c,v 1.4 2004/12/15 04:45:15 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: #include "smblib.h" ! 39: #include "genwrap.h" ! 40: ! 41: /****************************************************************************/ ! 42: /* Finds unused space in data file based on block allocation table and */ ! 43: /* marks space as used in allocation table. */ ! 44: /* File must be opened read/write DENY ALL */ ! 45: /* Returns offset to beginning of data (in bytes, not blocks) */ ! 46: /* Assumes smb_open_da() has been called */ ! 47: /* smb_close_da() should be called after */ ! 48: /* Returns negative on error */ ! 49: /****************************************************************************/ ! 50: long SMBCALL smb_allocdat(smb_t* smb, ulong length, ushort refs) ! 51: { ! 52: ushort i; ! 53: ulong j,l,blocks,offset=0L; ! 54: ! 55: if(smb->sda_fp==NULL) { ! 56: safe_snprintf(smb->last_error,sizeof(smb->last_error),"msgbase not open"); ! 57: return(SMB_ERR_NOT_OPEN); ! 58: } ! 59: blocks=smb_datblocks(length); ! 60: j=0; /* j is consecutive unused block counter */ ! 61: fflush(smb->sda_fp); ! 62: rewind(smb->sda_fp); ! 63: while(!feof(smb->sda_fp) && (long)offset>=0) { ! 64: if(smb_fread(smb,&i,sizeof(i),smb->sda_fp)!=sizeof(i)) ! 65: break; ! 66: offset+=SDT_BLOCK_LEN; ! 67: if(!i) j++; ! 68: else j=0; ! 69: if(j==blocks) { ! 70: offset-=(blocks*SDT_BLOCK_LEN); ! 71: break; ! 72: } ! 73: } ! 74: if((long)offset<0) { ! 75: safe_snprintf(smb->last_error,sizeof(smb->last_error),"invalid data offset: %lu",offset); ! 76: return(SMB_ERR_DAT_OFFSET); ! 77: } ! 78: clearerr(smb->sda_fp); ! 79: if(fseek(smb->sda_fp,(offset/SDT_BLOCK_LEN)*sizeof(refs),SEEK_SET)) { ! 80: return(SMB_ERR_SEEK); ! 81: } ! 82: for(l=0;l<blocks;l++) ! 83: if(!fwrite(&refs,sizeof(refs),1,smb->sda_fp)) { ! 84: safe_snprintf(smb->last_error,sizeof(smb->last_error) ! 85: ,"%d '%s' writing allocation bytes at offset %ld" ! 86: ,get_errno(),STRERROR(get_errno()) ! 87: ,((offset/SDT_BLOCK_LEN)+l)*sizeof(refs)); ! 88: return(SMB_ERR_WRITE); ! 89: } ! 90: fflush(smb->sda_fp); ! 91: return(offset); ! 92: } ! 93: ! 94: /****************************************************************************/ ! 95: /* Allocates space for data, but doesn't search for unused blocks */ ! 96: /* Returns negative on error */ ! 97: /****************************************************************************/ ! 98: long SMBCALL smb_fallocdat(smb_t* smb, ulong length, ushort refs) ! 99: { ! 100: ulong l,blocks,offset; ! 101: ! 102: if(smb->sda_fp==NULL) { ! 103: safe_snprintf(smb->last_error,sizeof(smb->last_error),"msgbase not open"); ! 104: return(SMB_ERR_NOT_OPEN); ! 105: } ! 106: fflush(smb->sda_fp); ! 107: clearerr(smb->sda_fp); ! 108: blocks=smb_datblocks(length); ! 109: if(fseek(smb->sda_fp,0L,SEEK_END)) { ! 110: return(SMB_ERR_SEEK); ! 111: } ! 112: offset=(ftell(smb->sda_fp)/sizeof(refs))*SDT_BLOCK_LEN; ! 113: if((long)offset<0) { ! 114: safe_snprintf(smb->last_error,sizeof(smb->last_error) ! 115: ,"invalid data offset: %lu",offset); ! 116: return(SMB_ERR_DAT_OFFSET); ! 117: } ! 118: for(l=0;l<blocks;l++) ! 119: if(!fwrite(&refs,sizeof(refs),1,smb->sda_fp)) ! 120: break; ! 121: fflush(smb->sda_fp); ! 122: if(l<blocks) { ! 123: safe_snprintf(smb->last_error,sizeof(smb->last_error) ! 124: ,"%d '%s' writing allocation bytes" ! 125: ,get_errno(),STRERROR(get_errno())); ! 126: return(SMB_ERR_WRITE); ! 127: } ! 128: return(offset); ! 129: } ! 130: ! 131: /****************************************************************************/ ! 132: /* De-allocates space for data */ ! 133: /* Returns non-zero on error */ ! 134: /****************************************************************************/ ! 135: int SMBCALL smb_freemsgdat(smb_t* smb, ulong offset, ulong length, ushort refs) ! 136: { ! 137: BOOL da_opened=FALSE; ! 138: int retval=0; ! 139: ushort i; ! 140: ulong l,blocks; ! 141: ulong sda_offset; ! 142: ! 143: if(smb->status.attr&SMB_HYPERALLOC) /* do nothing */ ! 144: return(SMB_SUCCESS); ! 145: ! 146: blocks=smb_datblocks(length); ! 147: ! 148: if(smb->sda_fp==NULL) { ! 149: if((i=smb_open_da(smb))!=SMB_SUCCESS) ! 150: return(i); ! 151: da_opened=TRUE; ! 152: } ! 153: ! 154: clearerr(smb->sda_fp); ! 155: for(l=0;l<blocks;l++) { ! 156: sda_offset=((offset/SDT_BLOCK_LEN)+l)*sizeof(i); ! 157: if(fseek(smb->sda_fp,sda_offset,SEEK_SET)) { ! 158: safe_snprintf(smb->last_error,sizeof(smb->last_error) ! 159: ,"%d '%s' seeking to %lu (0x%lX) of allocation file" ! 160: ,get_errno(),STRERROR(get_errno()) ! 161: ,sda_offset,sda_offset); ! 162: retval=SMB_ERR_SEEK; ! 163: break; ! 164: } ! 165: if(smb_fread(smb,&i,sizeof(i),smb->sda_fp)!=sizeof(i)) { ! 166: safe_snprintf(smb->last_error,sizeof(smb->last_error) ! 167: ,"%d '%s' reading allocation bytes at offset %ld" ! 168: ,get_errno(),STRERROR(get_errno()) ! 169: ,sda_offset); ! 170: retval=SMB_ERR_READ; ! 171: break; ! 172: } ! 173: if(refs==SMB_ALL_REFS || refs>i) ! 174: i=0; /* don't want to go negative */ ! 175: else ! 176: i-=refs; ! 177: if(fseek(smb->sda_fp,-(int)sizeof(i),SEEK_CUR)) { ! 178: safe_snprintf(smb->last_error,sizeof(smb->last_error) ! 179: ,"%d '%s' seeking backwards 2 bytes in allocation file" ! 180: ,get_errno(),STRERROR(get_errno())); ! 181: retval=SMB_ERR_SEEK; ! 182: break; ! 183: } ! 184: if(!fwrite(&i,sizeof(i),1,smb->sda_fp)) { ! 185: safe_snprintf(smb->last_error,sizeof(smb->last_error) ! 186: ,"%d '%s' writing allocation bytes at offset %ld" ! 187: ,get_errno(),STRERROR(get_errno()) ! 188: ,sda_offset); ! 189: retval=SMB_ERR_WRITE; ! 190: break; ! 191: } ! 192: } ! 193: fflush(smb->sda_fp); ! 194: if(da_opened) ! 195: smb_close_da(smb); ! 196: return(retval); ! 197: } ! 198: ! 199: /****************************************************************************/ ! 200: /* Adds to data allocation records for blocks starting at 'offset' */ ! 201: /* Returns non-zero on error */ ! 202: /****************************************************************************/ ! 203: int SMBCALL smb_incdat(smb_t* smb, ulong offset, ulong length, ushort refs) ! 204: { ! 205: ushort i; ! 206: ulong l,blocks; ! 207: ! 208: if(smb->sda_fp==NULL) { ! 209: safe_snprintf(smb->last_error,sizeof(smb->last_error),"msgbase not open"); ! 210: return(SMB_ERR_NOT_OPEN); ! 211: } ! 212: clearerr(smb->sda_fp); ! 213: blocks=smb_datblocks(length); ! 214: for(l=0;l<blocks;l++) { ! 215: if(fseek(smb->sda_fp,((offset/SDT_BLOCK_LEN)+l)*sizeof(i),SEEK_SET)) { ! 216: return(SMB_ERR_SEEK); ! 217: } ! 218: if(smb_fread(smb,&i,sizeof(i),smb->sda_fp)!=sizeof(i)) { ! 219: safe_snprintf(smb->last_error,sizeof(smb->last_error) ! 220: ,"%d '%s' reading allocation record at offset %ld" ! 221: ,get_errno(),STRERROR(get_errno()) ! 222: ,((offset/SDT_BLOCK_LEN)+l)*sizeof(i)); ! 223: return(SMB_ERR_READ); ! 224: } ! 225: i+=refs; ! 226: if(fseek(smb->sda_fp,-(int)sizeof(i),SEEK_CUR)) { ! 227: return(SMB_ERR_SEEK); ! 228: } ! 229: if(!fwrite(&i,sizeof(i),1,smb->sda_fp)) { ! 230: safe_snprintf(smb->last_error,sizeof(smb->last_error) ! 231: ,"%d '%s' writing allocation record at offset %ld" ! 232: ,get_errno(),STRERROR(get_errno()) ! 233: ,((offset/SDT_BLOCK_LEN)+l)*sizeof(i)); ! 234: return(SMB_ERR_WRITE); ! 235: } ! 236: } ! 237: fflush(smb->sda_fp); ! 238: return(SMB_SUCCESS); ! 239: } ! 240: ! 241: /****************************************************************************/ ! 242: /* Increments data allocation records (message references) by number of */ ! 243: /* header references specified (usually 1) */ ! 244: /* The opposite function of smb_freemsg() */ ! 245: /****************************************************************************/ ! 246: int SMBCALL smb_incmsg_dfields(smb_t* smb, smbmsg_t* msg, ushort refs) ! 247: { ! 248: int i=0; ! 249: BOOL da_opened=FALSE; ! 250: ushort x; ! 251: ! 252: if(smb->status.attr&SMB_HYPERALLOC) /* Nothing to do */ ! 253: return(SMB_SUCCESS); ! 254: ! 255: if(smb->sda_fp==NULL) { ! 256: if((i=smb_open_da(smb))!=SMB_SUCCESS) ! 257: return(i); ! 258: da_opened=TRUE; ! 259: } ! 260: ! 261: for(x=0;x<msg->hdr.total_dfields;x++) { ! 262: if((i=smb_incdat(smb,msg->hdr.offset+msg->dfield[x].offset ! 263: ,msg->dfield[x].length,refs))!=SMB_SUCCESS) ! 264: break; ! 265: } ! 266: ! 267: if(da_opened) ! 268: smb_close_da(smb); ! 269: return(i); ! 270: } ! 271: ! 272: /****************************************************************************/ ! 273: /* De-allocates blocks for header record */ ! 274: /* Returns non-zero on error */ ! 275: /****************************************************************************/ ! 276: int SMBCALL smb_freemsghdr(smb_t* smb, ulong offset, ulong length) ! 277: { ! 278: uchar c=0; ! 279: ulong l,blocks; ! 280: ! 281: if(smb->sha_fp==NULL) { ! 282: safe_snprintf(smb->last_error,sizeof(smb->last_error),"msgbase not open"); ! 283: return(SMB_ERR_NOT_OPEN); ! 284: } ! 285: clearerr(smb->sha_fp); ! 286: blocks=smb_hdrblocks(length); ! 287: if(fseek(smb->sha_fp,offset/SHD_BLOCK_LEN,SEEK_SET)) ! 288: return(SMB_ERR_SEEK); ! 289: for(l=0;l<blocks;l++) ! 290: if(!fwrite(&c,1,1,smb->sha_fp)) { ! 291: safe_snprintf(smb->last_error,sizeof(smb->last_error) ! 292: ,"%d '%s' writing allocation record" ! 293: ,get_errno(),STRERROR(get_errno())); ! 294: return(SMB_ERR_WRITE); ! 295: } ! 296: fflush(smb->sha_fp); ! 297: return(SMB_SUCCESS); ! 298: } ! 299: ! 300: /****************************************************************************/ ! 301: /****************************************************************************/ ! 302: int SMBCALL smb_freemsg_dfields(smb_t* smb, smbmsg_t* msg, ushort refs) ! 303: { ! 304: int i; ! 305: ushort x; ! 306: ! 307: for(x=0;x<msg->hdr.total_dfields;x++) { ! 308: if((i=smb_freemsgdat(smb,msg->hdr.offset+msg->dfield[x].offset ! 309: ,msg->dfield[x].length,refs))!=SMB_SUCCESS) ! 310: return(i); ! 311: } ! 312: return(SMB_SUCCESS); ! 313: } ! 314: ! 315: /****************************************************************************/ ! 316: /* Frees all allocated header and data blocks (1 reference) for 'msg' */ ! 317: /****************************************************************************/ ! 318: int SMBCALL smb_freemsg(smb_t* smb, smbmsg_t* msg) ! 319: { ! 320: int i; ! 321: ! 322: if(smb->status.attr&SMB_HYPERALLOC) /* Nothing to do */ ! 323: return(SMB_SUCCESS); ! 324: ! 325: if(!smb_valid_hdr_offset(smb,msg->idx.offset)) ! 326: return(SMB_ERR_HDR_OFFSET); ! 327: ! 328: if((i=smb_freemsg_dfields(smb,msg,1))!=SMB_SUCCESS) ! 329: return(i); ! 330: ! 331: return(smb_freemsghdr(smb,msg->idx.offset-smb->status.header_offset ! 332: ,msg->hdr.length)); ! 333: } ! 334: ! 335: /****************************************************************************/ ! 336: /* Finds unused space in header file based on block allocation table and */ ! 337: /* marks space as used in allocation table. */ ! 338: /* File must be opened read/write DENY ALL */ ! 339: /* Returns offset to beginning of header (in bytes, not blocks) */ ! 340: /* Assumes smb_open_ha() has been called */ ! 341: /* smb_close_ha() should be called after */ ! 342: /* Returns negative value on error */ ! 343: /****************************************************************************/ ! 344: long SMBCALL smb_allochdr(smb_t* smb, ulong length) ! 345: { ! 346: uchar c; ! 347: ulong i,l,blocks,offset=0; ! 348: ! 349: if(smb->sha_fp==NULL) { ! 350: safe_snprintf(smb->last_error,sizeof(smb->last_error),"msgbase not open"); ! 351: return(SMB_ERR_NOT_OPEN); ! 352: } ! 353: blocks=smb_hdrblocks(length); ! 354: i=0; /* i is consecutive unused block counter */ ! 355: fflush(smb->sha_fp); ! 356: rewind(smb->sha_fp); ! 357: while(!feof(smb->sha_fp)) { ! 358: if(smb_fread(smb,&c,sizeof(c),smb->sha_fp)!=sizeof(c)) ! 359: break; ! 360: offset+=SHD_BLOCK_LEN; ! 361: if(!c) i++; ! 362: else i=0; ! 363: if(i==blocks) { ! 364: offset-=(blocks*SHD_BLOCK_LEN); ! 365: break; ! 366: } ! 367: } ! 368: clearerr(smb->sha_fp); ! 369: if(fseek(smb->sha_fp,offset/SHD_BLOCK_LEN,SEEK_SET)) ! 370: return(SMB_ERR_SEEK); ! 371: ! 372: for(l=0;l<blocks;l++) ! 373: if(fputc(1,smb->sha_fp)!=1) { ! 374: safe_snprintf(smb->last_error,sizeof(smb->last_error) ! 375: ,"%d '%s' writing allocation record" ! 376: ,get_errno(),STRERROR(get_errno())); ! 377: return(SMB_ERR_WRITE); ! 378: } ! 379: fflush(smb->sha_fp); ! 380: return(offset); ! 381: } ! 382: ! 383: /****************************************************************************/ ! 384: /* Allocates space for index, but doesn't search for unused blocks */ ! 385: /* Returns negative value on error */ ! 386: /****************************************************************************/ ! 387: long SMBCALL smb_fallochdr(smb_t* smb, ulong length) ! 388: { ! 389: uchar c=1; ! 390: ulong l,blocks,offset; ! 391: ! 392: if(smb->sha_fp==NULL) { ! 393: safe_snprintf(smb->last_error,sizeof(smb->last_error),"msgbase not open"); ! 394: return(SMB_ERR_NOT_OPEN); ! 395: } ! 396: blocks=smb_hdrblocks(length); ! 397: fflush(smb->sha_fp); ! 398: clearerr(smb->sha_fp); ! 399: if(fseek(smb->sha_fp,0L,SEEK_END)) ! 400: return(SMB_ERR_SEEK); ! 401: offset=ftell(smb->sha_fp)*SHD_BLOCK_LEN; ! 402: for(l=0;l<blocks;l++) ! 403: if(!fwrite(&c,1,1,smb->sha_fp)) { ! 404: safe_snprintf(smb->last_error,sizeof(smb->last_error) ! 405: ,"%d '%s' writing allocation record" ! 406: ,get_errno(),STRERROR(get_errno())); ! 407: return(SMB_ERR_WRITE); ! 408: } ! 409: fflush(smb->sha_fp); ! 410: return(offset); ! 411: } ! 412: ! 413: /************************************************************************/ ! 414: /* Allocate header blocks using Hyper Allocation */ ! 415: /* this function should be most likely not be called from anywhere but */ ! 416: /* smb_addmsghdr() */ ! 417: /************************************************************************/ ! 418: long SMBCALL smb_hallochdr(smb_t* smb) ! 419: { ! 420: ulong offset; ! 421: ! 422: if(smb->shd_fp==NULL) { ! 423: safe_snprintf(smb->last_error,sizeof(smb->last_error),"msgbase not open"); ! 424: return(SMB_ERR_NOT_OPEN); ! 425: } ! 426: fflush(smb->shd_fp); ! 427: if(fseek(smb->shd_fp,0L,SEEK_END)) ! 428: return(SMB_ERR_SEEK); ! 429: offset=ftell(smb->shd_fp); ! 430: if(offset<smb->status.header_offset) /* Header file truncated?!? */ ! 431: return(smb->status.header_offset); ! 432: ! 433: offset-=smb->status.header_offset; /* SMB headers not included */ ! 434: ! 435: /* Even block boundry */ ! 436: offset+=PAD_LENGTH_FOR_ALIGNMENT(offset,SHD_BLOCK_LEN); ! 437: ! 438: return(offset); ! 439: } ! 440: ! 441: /************************************************************************/ ! 442: /* Allocate data blocks using Hyper Allocation */ ! 443: /* smb_locksmbhdr() should be called before this function and not */ ! 444: /* unlocked until all data fields for this message have been written */ ! 445: /* to the SDT file */ ! 446: /************************************************************************/ ! 447: long SMBCALL smb_hallocdat(smb_t* smb) ! 448: { ! 449: long offset; ! 450: ! 451: if(smb->sdt_fp==NULL) { ! 452: safe_snprintf(smb->last_error,sizeof(smb->last_error) ! 453: ,"msgbase not open"); ! 454: return(SMB_ERR_NOT_OPEN); ! 455: } ! 456: fflush(smb->sdt_fp); ! 457: offset=filelength(fileno(smb->sdt_fp)); ! 458: if(offset<0) { ! 459: safe_snprintf(smb->last_error,sizeof(smb->last_error) ! 460: ,"invalid file length: %lu",(ulong)offset); ! 461: return(SMB_ERR_FILE_LEN); ! 462: } ! 463: if(fseek(smb->sdt_fp,0L,SEEK_END)) ! 464: return(SMB_ERR_SEEK); ! 465: offset=ftell(smb->sdt_fp); ! 466: if(offset<0) { ! 467: safe_snprintf(smb->last_error,sizeof(smb->last_error) ! 468: ,"invalid file offset: %ld",offset); ! 469: return(SMB_ERR_DAT_OFFSET); ! 470: } ! 471: ! 472: /* Make sure even block boundry */ ! 473: offset+=PAD_LENGTH_FOR_ALIGNMENT(offset,SDT_BLOCK_LEN); ! 474: ! 475: return(offset); ! 476: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.