|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.