Annotation of sbbs/src/smblib/smballoc.c, revision 1.1.1.2

1.1       root        1: /* smballoc.c */
                      2: 
                      3: /* Synchronet message base (SMB) alloc/free routines */
                      4: 
1.1.1.2 ! root        5: /* $Id: smballoc.c,v 1.6 2007/07/10 22:20:00 deuce Exp $ */
1.1       root        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: /****************************************************************************/
1.1.1.2 ! root       50: long SMBCALL smb_allocdat(smb_t* smb, ulong length, uint16_t refs)
1.1       root       51: {
1.1.1.2 ! root       52:     uint16_t  i;
1.1       root       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: /****************************************************************************/
1.1.1.2 ! root       98: long SMBCALL smb_fallocdat(smb_t* smb, ulong length, uint16_t refs)
1.1       root       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: /****************************************************************************/
1.1.1.2 ! root      135: int SMBCALL smb_freemsgdat(smb_t* smb, ulong offset, ulong length, uint16_t refs)
1.1       root      136: {
                    137:        BOOL    da_opened=FALSE;
                    138:        int             retval=SMB_SUCCESS;
1.1.1.2 ! root      139:        uint16_t        i;
1.1       root      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: /****************************************************************************/
1.1.1.2 ! root      203: int SMBCALL smb_incdat(smb_t* smb, ulong offset, ulong length, uint16_t refs)
1.1       root      204: {
1.1.1.2 ! root      205:        uint16_t        i;
1.1       root      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: /****************************************************************************/
1.1.1.2 ! root      245: int SMBCALL smb_incmsg_dfields(smb_t* smb, smbmsg_t* msg, uint16_t refs)
1.1       root      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: /****************************************************************************/
1.1.1.2 ! root      300: int SMBCALL smb_freemsg_dfields(smb_t* smb, smbmsg_t* msg, uint16_t refs)
1.1       root      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: }

unix.superglobalmegacorp.com

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