Annotation of sbbs/smblib/smballoc.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.