|
|
1.1 ! root 1: /* smballoc.c */ ! 2: ! 3: /* Synchronet message base (SMB) alloc/free routines */ ! 4: ! 5: /* $Id: smballoc.c,v 1.5 2005/09/30 09:04:31 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 2005 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=SMB_SUCCESS; ! 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: return fflush(smb->sda_fp); /* SMB_SUCCESS == 0 */ ! 238: } ! 239: ! 240: /****************************************************************************/ ! 241: /* Increments data allocation records (message references) by number of */ ! 242: /* header references specified (usually 1) */ ! 243: /* The opposite function of smb_freemsg() */ ! 244: /****************************************************************************/ ! 245: int SMBCALL smb_incmsg_dfields(smb_t* smb, smbmsg_t* msg, ushort refs) ! 246: { ! 247: int i=SMB_SUCCESS; ! 248: BOOL da_opened=FALSE; ! 249: ushort x; ! 250: ! 251: if(smb->status.attr&SMB_HYPERALLOC) /* Nothing to do */ ! 252: return(SMB_SUCCESS); ! 253: ! 254: if(smb->sda_fp==NULL) { ! 255: if((i=smb_open_da(smb))!=SMB_SUCCESS) ! 256: return(i); ! 257: da_opened=TRUE; ! 258: } ! 259: ! 260: for(x=0;x<msg->hdr.total_dfields;x++) { ! 261: if((i=smb_incdat(smb,msg->hdr.offset+msg->dfield[x].offset ! 262: ,msg->dfield[x].length,refs))!=SMB_SUCCESS) ! 263: break; ! 264: } ! 265: ! 266: if(da_opened) ! 267: smb_close_da(smb); ! 268: return(i); ! 269: } ! 270: ! 271: /****************************************************************************/ ! 272: /* De-allocates blocks for header record */ ! 273: /* Returns non-zero on error */ ! 274: /****************************************************************************/ ! 275: int SMBCALL smb_freemsghdr(smb_t* smb, ulong offset, ulong length) ! 276: { ! 277: uchar c=0; ! 278: ulong l,blocks; ! 279: ! 280: if(smb->sha_fp==NULL) { ! 281: safe_snprintf(smb->last_error,sizeof(smb->last_error),"msgbase not open"); ! 282: return(SMB_ERR_NOT_OPEN); ! 283: } ! 284: clearerr(smb->sha_fp); ! 285: blocks=smb_hdrblocks(length); ! 286: if(fseek(smb->sha_fp,offset/SHD_BLOCK_LEN,SEEK_SET)) ! 287: return(SMB_ERR_SEEK); ! 288: for(l=0;l<blocks;l++) ! 289: if(!fwrite(&c,1,1,smb->sha_fp)) { ! 290: safe_snprintf(smb->last_error,sizeof(smb->last_error) ! 291: ,"%d '%s' writing allocation record" ! 292: ,get_errno(),STRERROR(get_errno())); ! 293: return(SMB_ERR_WRITE); ! 294: } ! 295: return fflush(smb->sha_fp); /* SMB_SUCCESS == 0 */ ! 296: } ! 297: ! 298: /****************************************************************************/ ! 299: /****************************************************************************/ ! 300: int SMBCALL smb_freemsg_dfields(smb_t* smb, smbmsg_t* msg, ushort refs) ! 301: { ! 302: int i; ! 303: ushort x; ! 304: ! 305: for(x=0;x<msg->hdr.total_dfields;x++) { ! 306: if((i=smb_freemsgdat(smb,msg->hdr.offset+msg->dfield[x].offset ! 307: ,msg->dfield[x].length,refs))!=SMB_SUCCESS) ! 308: return(i); ! 309: } ! 310: return(SMB_SUCCESS); ! 311: } ! 312: ! 313: /****************************************************************************/ ! 314: /* Frees all allocated header and data blocks (1 reference) for 'msg' */ ! 315: /****************************************************************************/ ! 316: int SMBCALL smb_freemsg(smb_t* smb, smbmsg_t* msg) ! 317: { ! 318: int i; ! 319: ! 320: if(smb->status.attr&SMB_HYPERALLOC) /* Nothing to do */ ! 321: return(SMB_SUCCESS); ! 322: ! 323: if(!smb_valid_hdr_offset(smb,msg->idx.offset)) ! 324: return(SMB_ERR_HDR_OFFSET); ! 325: ! 326: if((i=smb_freemsg_dfields(smb,msg,1))!=SMB_SUCCESS) ! 327: return(i); ! 328: ! 329: return(smb_freemsghdr(smb,msg->idx.offset-smb->status.header_offset ! 330: ,msg->hdr.length)); ! 331: } ! 332: ! 333: /****************************************************************************/ ! 334: /* Finds unused space in header file based on block allocation table and */ ! 335: /* marks space as used in allocation table. */ ! 336: /* File must be opened read/write DENY ALL */ ! 337: /* Returns offset to beginning of header (in bytes, not blocks) */ ! 338: /* Assumes smb_open_ha() has been called */ ! 339: /* smb_close_ha() should be called after */ ! 340: /* Returns negative value on error */ ! 341: /****************************************************************************/ ! 342: long SMBCALL smb_allochdr(smb_t* smb, ulong length) ! 343: { ! 344: uchar c; ! 345: ulong i,l,blocks,offset=0; ! 346: ! 347: if(smb->sha_fp==NULL) { ! 348: safe_snprintf(smb->last_error,sizeof(smb->last_error),"msgbase not open"); ! 349: return(SMB_ERR_NOT_OPEN); ! 350: } ! 351: blocks=smb_hdrblocks(length); ! 352: i=0; /* i is consecutive unused block counter */ ! 353: fflush(smb->sha_fp); ! 354: rewind(smb->sha_fp); ! 355: while(!feof(smb->sha_fp)) { ! 356: if(smb_fread(smb,&c,sizeof(c),smb->sha_fp)!=sizeof(c)) ! 357: break; ! 358: offset+=SHD_BLOCK_LEN; ! 359: if(!c) i++; ! 360: else i=0; ! 361: if(i==blocks) { ! 362: offset-=(blocks*SHD_BLOCK_LEN); ! 363: break; ! 364: } ! 365: } ! 366: clearerr(smb->sha_fp); ! 367: if(fseek(smb->sha_fp,offset/SHD_BLOCK_LEN,SEEK_SET)) ! 368: return(SMB_ERR_SEEK); ! 369: ! 370: for(l=0;l<blocks;l++) ! 371: if(fputc(1,smb->sha_fp)!=1) { ! 372: safe_snprintf(smb->last_error,sizeof(smb->last_error) ! 373: ,"%d '%s' writing allocation record" ! 374: ,get_errno(),STRERROR(get_errno())); ! 375: return(SMB_ERR_WRITE); ! 376: } ! 377: fflush(smb->sha_fp); ! 378: return(offset); ! 379: } ! 380: ! 381: /****************************************************************************/ ! 382: /* Allocates space for index, but doesn't search for unused blocks */ ! 383: /* Returns negative value on error */ ! 384: /****************************************************************************/ ! 385: long SMBCALL smb_fallochdr(smb_t* smb, ulong length) ! 386: { ! 387: uchar c=1; ! 388: ulong l,blocks,offset; ! 389: ! 390: if(smb->sha_fp==NULL) { ! 391: safe_snprintf(smb->last_error,sizeof(smb->last_error),"msgbase not open"); ! 392: return(SMB_ERR_NOT_OPEN); ! 393: } ! 394: blocks=smb_hdrblocks(length); ! 395: fflush(smb->sha_fp); ! 396: clearerr(smb->sha_fp); ! 397: if(fseek(smb->sha_fp,0L,SEEK_END)) ! 398: return(SMB_ERR_SEEK); ! 399: offset=ftell(smb->sha_fp)*SHD_BLOCK_LEN; ! 400: for(l=0;l<blocks;l++) ! 401: if(!fwrite(&c,1,1,smb->sha_fp)) { ! 402: safe_snprintf(smb->last_error,sizeof(smb->last_error) ! 403: ,"%d '%s' writing allocation record" ! 404: ,get_errno(),STRERROR(get_errno())); ! 405: return(SMB_ERR_WRITE); ! 406: } ! 407: fflush(smb->sha_fp); ! 408: return(offset); ! 409: } ! 410: ! 411: /************************************************************************/ ! 412: /* Allocate header blocks using Hyper Allocation */ ! 413: /* this function should be most likely not be called from anywhere but */ ! 414: /* smb_addmsghdr() */ ! 415: /************************************************************************/ ! 416: long SMBCALL smb_hallochdr(smb_t* smb) ! 417: { ! 418: ulong offset; ! 419: ! 420: if(smb->shd_fp==NULL) { ! 421: safe_snprintf(smb->last_error,sizeof(smb->last_error),"msgbase not open"); ! 422: return(SMB_ERR_NOT_OPEN); ! 423: } ! 424: fflush(smb->shd_fp); ! 425: if(fseek(smb->shd_fp,0L,SEEK_END)) ! 426: return(SMB_ERR_SEEK); ! 427: offset=ftell(smb->shd_fp); ! 428: if(offset<smb->status.header_offset) /* Header file truncated?!? */ ! 429: return(smb->status.header_offset); ! 430: ! 431: offset-=smb->status.header_offset; /* SMB headers not included */ ! 432: ! 433: /* Even block boundry */ ! 434: offset+=PAD_LENGTH_FOR_ALIGNMENT(offset,SHD_BLOCK_LEN); ! 435: ! 436: return(offset); ! 437: } ! 438: ! 439: /************************************************************************/ ! 440: /* Allocate data blocks using Hyper Allocation */ ! 441: /* smb_locksmbhdr() should be called before this function and not */ ! 442: /* unlocked until all data fields for this message have been written */ ! 443: /* to the SDT file */ ! 444: /************************************************************************/ ! 445: long SMBCALL smb_hallocdat(smb_t* smb) ! 446: { ! 447: long offset; ! 448: ! 449: if(smb->sdt_fp==NULL) { ! 450: safe_snprintf(smb->last_error,sizeof(smb->last_error) ! 451: ,"msgbase not open"); ! 452: return(SMB_ERR_NOT_OPEN); ! 453: } ! 454: fflush(smb->sdt_fp); ! 455: offset=filelength(fileno(smb->sdt_fp)); ! 456: if(offset<0) { ! 457: safe_snprintf(smb->last_error,sizeof(smb->last_error) ! 458: ,"invalid file length: %lu",(ulong)offset); ! 459: return(SMB_ERR_FILE_LEN); ! 460: } ! 461: if(fseek(smb->sdt_fp,0L,SEEK_END)) ! 462: return(SMB_ERR_SEEK); ! 463: offset=ftell(smb->sdt_fp); ! 464: if(offset<0) { ! 465: safe_snprintf(smb->last_error,sizeof(smb->last_error) ! 466: ,"invalid file offset: %ld",offset); ! 467: return(SMB_ERR_DAT_OFFSET); ! 468: } ! 469: ! 470: /* Make sure even block boundry */ ! 471: offset+=PAD_LENGTH_FOR_ALIGNMENT(offset,SDT_BLOCK_LEN); ! 472: ! 473: return(offset); ! 474: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.