|
|
1.1 root 1: /* smblib.c */
2:
3: /* Synchronet message base (SMB) library routines */
4:
5: /* $Id: smblib.c,v 1.8 2000/11/04 12:03:51 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 2000 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: #if defined __WATCOMC__ || defined __TURBOC__
39: #include <mem.h>
40: #else
41: #include <memory.h>
42: #endif
43:
44: #ifdef __WATCOMC__
45: #include <dos.h>
46: #elif defined __TURBOC__
47: #include <dir.h>
48: #endif
49:
50: /* ANSI C Library headers */
51: #include <malloc.h>
52: #include <time.h>
53: #include <errno.h>
54: #include <fcntl.h>
55: #include <stdio.h>
56: #include <stdlib.h>
57: #include <string.h>
58: #include <sys/stat.h>
59: #include <sys/types.h>
60:
61: /* SMB-specific headers */
62: #include "smblib.h"
63: #include "smbwrap.h"
64:
65: /* Use smb_ver() and smb_lib_ver() to obtain these values */
66: #define SMBLIB_VERSION "2.13" /* SMB library version */
67: #define SMB_VERSION 0x0121 /* SMB format version */
68: /* High byte major, low byte minor */
69:
70: int SMBCALL smb_ver(void)
71: {
72: return(SMB_VERSION);
73: }
74:
75: char* SMBCALL smb_lib_ver(void)
76: {
77: return(SMBLIB_VERSION);
78: }
79:
80: /****************************************************************************/
81: /* Open a message base of name 'smb->file' */
82: /* Opens files for READing messages or updating message indices only */
83: /****************************************************************************/
84: int SMBCALL smb_open(smb_t* smb)
85: {
86: int file;
87: char str[128];
88: smbhdr_t hdr;
89:
90: if(!smb->retry_time)
91: smb->retry_time=10;
92: smb->shd_fp=smb->sdt_fp=smb->sid_fp=NULL;
93: sprintf(str,"%s.shd",smb->file);
94: if((file=sopen(str,O_RDWR|O_CREAT|O_BINARY,SH_DENYNO))==-1
95: || (smb->shd_fp=fdopen(file,"r+b"))==NULL) {
96: sprintf(smb->last_error,"%d opening %s",errno,str);
97: if(file!=-1)
98: close(file);
99: return(2);
100: }
101:
102: if(filelength(file)>=sizeof(smbhdr_t)) {
103: setvbuf(smb->shd_fp,smb->shd_buf,_IONBF,SHD_BLOCK_LEN);
104: if(smb_locksmbhdr(smb)!=0) {
105: smb_close(smb);
106: /* smb_lockmsghdr set last_error */
107: return(-1);
108: }
109: memset(&hdr,0,sizeof(smbhdr_t));
110: if(fread(&hdr,sizeof(smbhdr_t),1,smb->shd_fp)!=1) {
111: sprintf(smb->last_error,"reading header");
112: smb_close(smb);
113: return(-10);
114: }
115: if(memcmp(hdr.id,"SMB\x1a",4)) {
116: sprintf(smb->last_error,"corrupt header id: %.4s",hdr.id);
117: smb_close(smb);
118: return(-2);
119: }
120: if(hdr.version<0x110) { /* Compatibility check */
121: sprintf(smb->last_error,"insufficient header version: %X",hdr.version);
122: smb_close(smb);
123: return(-3);
124: }
125: if(fread(&(smb->status),1,sizeof(smbstatus_t),smb->shd_fp)
126: !=sizeof(smbstatus_t)) {
127: sprintf(smb->last_error,"failed to read status");
128: smb_close(smb);
129: return(-4);
130: }
131: smb_unlocksmbhdr(smb);
132: rewind(smb->shd_fp);
133: }
134:
135: setvbuf(smb->shd_fp,smb->shd_buf,_IOFBF,SHD_BLOCK_LEN);
136:
137: sprintf(str,"%s.sdt",smb->file);
138: if((file=sopen(str,O_RDWR|O_CREAT|O_BINARY,SH_DENYNO))==-1
139: || (smb->sdt_fp=fdopen(file,"r+b"))==NULL) {
140: sprintf(smb->last_error,"%d opening %s",errno,str);
141: if(file!=-1)
142: close(file);
143: smb_close(smb);
144: return(1);
145: }
146: setvbuf(smb->sdt_fp,NULL,_IOFBF,2*1024);
147:
148: sprintf(str,"%s.sid",smb->file);
149: if((file=sopen(str,O_RDWR|O_CREAT|O_BINARY,SH_DENYNO))==-1
150: || (smb->sid_fp=fdopen(file,"r+b"))==NULL) {
151: sprintf(smb->last_error,"%d opening %s",errno,str);
152: if(file!=-1)
153: close(file);
154: smb_close(smb);
155: return(3);
156: }
157: setvbuf(smb->sid_fp,NULL,_IOFBF,2*1024);
158:
159: return(0);
160: }
161:
162: /****************************************************************************/
163: /* Closes the currently open message base */
164: /****************************************************************************/
165: void SMBCALL smb_close(smb_t* smb)
166: {
167: if(smb->shd_fp!=NULL) {
168: smb_unlocksmbhdr(smb); /* In case it's been locked */
169: fclose(smb->shd_fp);
170: }
171: if(smb->sid_fp!=NULL)
172: fclose(smb->sid_fp);
173: if(smb->sdt_fp!=NULL)
174: fclose(smb->sdt_fp);
175: smb->sid_fp=smb->shd_fp=smb->sdt_fp=NULL;
176: }
177:
178: /****************************************************************************/
179: /* Opens the data block allocation table message base 'smb->file' */
180: /* Retrys for retry_time number of seconds */
181: /* Return 0 on success, non-zero otherwise */
182: /****************************************************************************/
183: int SMBCALL smb_open_da(smb_t* smb)
184: {
185: int file;
186: char str[128];
187: ulong start=0;
188:
189: sprintf(str,"%s.sda",smb->file);
190: while(1) {
191: if((file=sopen(str,O_RDWR|O_CREAT|O_BINARY,SH_DENYRW))!=-1)
192: break;
193: if(errno!=EACCES) {
194: sprintf(smb->last_error,"%d opening %s",errno,str);
195: return(-1);
196: }
197: if(!start)
198: start=time(NULL);
199: else
200: if(time(NULL)-start>=smb->retry_time) {
201: sprintf(smb->last_error,"timeout opening %s",str);
202: return(-2);
203: }
204: }
205: if((smb->sda_fp=fdopen(file,"r+b"))==NULL) {
206: sprintf(smb->last_error,"%d fdopening %s",errno,str);
207: close(file);
208: return(-3);
209: }
210: setvbuf(smb->sda_fp,NULL,_IOFBF,2*1024);
211: return(0);
212: }
213:
214: void SMBCALL smb_close_da(smb_t* smb)
215: {
216: if(smb->sda_fp!=NULL)
217: fclose(smb->sda_fp);
218: smb->sda_fp=NULL;
219: }
220:
221: /****************************************************************************/
222: /* Opens the header block allocation table for message base 'smb.file' */
223: /* Retrys for smb.retry_time number of seconds */
224: /* Return 0 on success, non-zero otherwise */
225: /****************************************************************************/
226: int SMBCALL smb_open_ha(smb_t* smb)
227: {
228: int file;
229: char str[128];
230: ulong start=0;
231:
232: sprintf(str,"%s.sha",smb->file);
233: while(1) {
234: if((file=sopen(str,O_RDWR|O_CREAT|O_BINARY,SH_DENYRW))!=-1)
235: break;
236: if(errno!=EACCES) {
237: sprintf(smb->last_error,"%d opening %s",errno,str);
238: return(-1);
239: }
240: if(!start)
241: start=time(NULL);
242: else
243: if(time(NULL)-start>=smb->retry_time) {
244: sprintf(smb->last_error,"timeout opening %s",str);
245: return(-2);
246: }
247: }
248: if((smb->sha_fp=fdopen(file,"r+b"))==NULL) {
249: sprintf(smb->last_error,"%d opening %s",errno,str);
250: close(file);
251: return(-3);
252: }
253: setvbuf(smb->sha_fp,NULL,_IOFBF,2*1024);
254: return(0);
255: }
256:
257: void SMBCALL smb_close_ha(smb_t* smb)
258: {
259: if(smb->sha_fp!=NULL)
260: fclose(smb->sha_fp);
261: smb->sha_fp=NULL;
262: }
263:
264: /****************************************************************************/
265: /* If the parameter 'push' is non-zero, this function stores the currently */
266: /* open message base to the "virtual" smb stack. Up to SMB_STACK_LEN */
267: /* message bases may be stored (defined in SMBDEFS.H). */
268: /* The parameter 'op' is the operation to perform on the stack. Either */
269: /* SMB_STACK_PUSH, SMB_STACK_POP, or SMB_STACK_XCHNG */
270: /* If the operation is SMB_STACK_POP, this function restores a message base */
271: /* previously saved with a SMB_STACK_PUSH call to this same function. */
272: /* If the operation is SMB_STACK_XCHNG, then the current message base is */
273: /* exchanged with the message base on the top of the stack (most recently */
274: /* pushed. */
275: /* If the current message base is not open, the SMB_STACK_PUSH and */
276: /* SMB_STACK_XCHNG operations do nothing */
277: /* Returns 0 on success, non-zero if stack full. */
278: /* If operation is SMB_STACK_POP or SMB_STACK_XCHNG, it always returns 0. */
279: /****************************************************************************/
280: int SMBCALL smb_stack(smb_t* smb, int op)
281: {
282: static char stack_file[SMB_STACK_LEN][128];
283: static FILE* stack_sdt[SMB_STACK_LEN],
284: *stack_shd[SMB_STACK_LEN],
285: *stack_sid[SMB_STACK_LEN],
286: *stack_sda[SMB_STACK_LEN],
287: *stack_sha[SMB_STACK_LEN];
288: static int stack_idx;
289: char tmp_file[128];
290: FILE *tmp_sdt,
291: *tmp_shd,
292: *tmp_sid,
293: *tmp_sda,
294: *tmp_sha;
295:
296: if(op==SMB_STACK_PUSH) {
297: if(stack_idx>=SMB_STACK_LEN) {
298: sprintf(smb->last_error,"SMB stack overflow");
299: return(1);
300: }
301: if(smb->shd_fp==NULL || smb->sdt_fp==NULL || smb->sid_fp==NULL)
302: return(0); /* Msg base not open */
303: memcpy(stack_file[stack_idx],smb->file,128);
304: stack_sdt[stack_idx]=smb->sdt_fp;
305: stack_shd[stack_idx]=smb->shd_fp;
306: stack_sid[stack_idx]=smb->sid_fp;
307: stack_sda[stack_idx]=smb->sda_fp;
308: stack_sha[stack_idx]=smb->sha_fp;
309: stack_idx++;
310: return(0);
311: }
312: /* pop or xchng */
313: if(!stack_idx) /* Nothing on the stack, so do nothing */
314: return(0);
315: if(op==SMB_STACK_XCHNG) {
316: if(!smb->shd_fp)
317: return(0);
318: memcpy(tmp_file,smb->file,128);
319: tmp_sdt=smb->sdt_fp;
320: tmp_shd=smb->shd_fp;
321: tmp_sid=smb->sid_fp;
322: tmp_sda=smb->sda_fp;
323: tmp_sha=smb->sha_fp;
324: }
325:
326: stack_idx--;
327: memcpy(smb->file,stack_file[stack_idx],128);
328: smb->sdt_fp=stack_sdt[stack_idx];
329: smb->shd_fp=stack_shd[stack_idx];
330: smb->sid_fp=stack_sid[stack_idx];
331: smb->sda_fp=stack_sda[stack_idx];
332: smb->sha_fp=stack_sha[stack_idx];
333: if(op==SMB_STACK_XCHNG) {
334: stack_idx++;
335: memcpy(stack_file[stack_idx-1],tmp_file,128);
336: stack_sdt[stack_idx-1]=tmp_sdt;
337: stack_shd[stack_idx-1]=tmp_shd;
338: stack_sid[stack_idx-1]=tmp_sid;
339: stack_sda[stack_idx-1]=tmp_sda;
340: stack_sha[stack_idx-1]=tmp_sha;
341: }
342: return(0);
343: }
344:
345: /****************************************************************************/
346: /* Truncates header file */
347: /* Retrys for smb.retry_time number of seconds */
348: /* Return 0 on success, non-zero otherwise */
349: /****************************************************************************/
350: int SMBCALL smb_trunchdr(smb_t* smb)
351: {
352: ulong start=0;
353:
354: rewind(smb->shd_fp);
355: while(1) {
356: if(!chsize(fileno(smb->shd_fp),0L))
357: break;
358: if(errno!=EACCES) {
359: sprintf(smb->last_error,"%d changing header file size",errno);
360: return(-1);
361: }
362: if(!start)
363: start=time(NULL);
364: else
365: if(time(NULL)-start>=smb->retry_time) { /* Time-out */
366: sprintf(smb->last_error,"timeout changing header file size");
367: return(-2);
368: }
369: }
370: return(0);
371: }
372:
373: /*********************************/
374: /* Message Base Header Functions */
375: /*********************************/
376:
377: /****************************************************************************/
378: /* Attempts for smb.retry_time number of seconds to lock the msg base hdr */
379: /****************************************************************************/
380: int SMBCALL smb_locksmbhdr(smb_t* smb)
381: {
382: ulong start=0;
383:
384: while(1) {
385: if(!lock(fileno(smb->shd_fp),0L,sizeof(smbhdr_t)+sizeof(smbstatus_t)))
386: return(0);
387: if(!start)
388: start=time(NULL);
389: else
390: if(time(NULL)-start>=smb->retry_time)
391: break;
392: /* In case we've already locked it */
393: unlock(fileno(smb->shd_fp),0L,sizeof(smbhdr_t)+sizeof(smbstatus_t));
394: }
395: sprintf(smb->last_error,"timeout locking header");
396: return(-1);
397: }
398:
399: /****************************************************************************/
400: /* Read the SMB header from the header file and place into smb.status */
401: /****************************************************************************/
402: int SMBCALL smb_getstatus(smb_t* smb)
403: {
404: int i;
405:
406: setvbuf(smb->shd_fp,smb->shd_buf,_IONBF,SHD_BLOCK_LEN);
407: clearerr(smb->shd_fp);
408: fseek(smb->shd_fp,sizeof(smbhdr_t),SEEK_SET);
409: i=fread(&(smb->status),1,sizeof(smbstatus_t),smb->shd_fp);
410: setvbuf(smb->shd_fp,smb->shd_buf,_IOFBF,SHD_BLOCK_LEN);
411: if(i==sizeof(smbstatus_t))
412: return(0);
413: sprintf(smb->last_error,"read %d instead of %d",i,sizeof(smbstatus_t));
414: return(1);
415: }
416:
417: /****************************************************************************/
418: /* Writes message base header */
419: /****************************************************************************/
420: int SMBCALL smb_putstatus(smb_t* smb)
421: {
422: int i;
423:
424: clearerr(smb->shd_fp);
425: fseek(smb->shd_fp,sizeof(smbhdr_t),SEEK_SET);
426: i=fwrite(&(smb->status),1,sizeof(smbstatus_t),smb->shd_fp);
427: fflush(smb->shd_fp);
428: if(i==sizeof(smbstatus_t))
429: return(0);
430: sprintf(smb->last_error,"wrote %d instead of %d",i,sizeof(smbstatus_t));
431: return(1);
432: }
433:
434: /****************************************************************************/
435: /* Unlocks previously locks message base header */
436: /****************************************************************************/
437: int SMBCALL smb_unlocksmbhdr(smb_t* smb)
438: {
439: return(unlock(fileno(smb->shd_fp),0L,sizeof(smbhdr_t)+sizeof(smbstatus_t)));
440: }
441:
442: /********************************/
443: /* Individual Message Functions */
444: /********************************/
445:
446: /****************************************************************************/
447: /* Attempts for smb.retry_time number of seconds to lock the hdr for 'msg' */
448: /****************************************************************************/
449: int SMBCALL smb_lockmsghdr(smb_t* smb, smbmsg_t* msg)
450: {
451: ulong start=0;
452:
453: while(1) {
454: if(!lock(fileno(smb->shd_fp),msg->idx.offset,sizeof(msghdr_t)))
455: return(0);
456: if(!start)
457: start=time(NULL);
458: else
459: if(time(NULL)-start>=smb->retry_time)
460: break;
461: /* In case we've already locked it */
462: unlock(fileno(smb->shd_fp),msg->idx.offset,sizeof(msghdr_t));
463: }
464: sprintf(smb->last_error,"timeout locking header");
465: return(-1);
466: }
467:
468: /****************************************************************************/
469: /* Fills msg->idx with message index based on msg->hdr.number */
470: /* OR if msg->hdr.number is 0, based on msg->offset (record offset). */
471: /* if msg.hdr.number does not equal 0, then msg->offset is filled too. */
472: /* Either msg->hdr.number or msg->offset must be initialized before */
473: /* calling this function */
474: /* Returns 1 if message number wasn't found, 0 if it was */
475: /****************************************************************************/
476: int SMBCALL smb_getmsgidx(smb_t* smb, smbmsg_t* msg)
477: {
478: idxrec_t idx;
479: ulong l,length,total,bot,top;
480:
481: clearerr(smb->sid_fp);
482: if(!msg->hdr.number) {
483: fseek(smb->sid_fp,msg->offset*sizeof(idxrec_t),SEEK_SET);
484: if(!fread(&msg->idx,sizeof(idxrec_t),1,smb->sid_fp)) {
485: sprintf(smb->last_error,"reading index");
486: return(1);
487: }
488: return(0);
489: }
490:
491: length=filelength(fileno(smb->sid_fp));
492: if(!length) {
493: sprintf(smb->last_error,"invalid index file length: %ld",length);
494: return(1);
495: }
496: total=length/sizeof(idxrec_t);
497: if(!total) {
498: sprintf(smb->last_error,"invalid index file length: %ld",length);
499: return(1);
500: }
501:
502: bot=0;
503: top=total;
504: l=total/2; /* Start at middle index */
505: while(1) {
506: fseek(smb->sid_fp,l*sizeof(idxrec_t),SEEK_SET);
507: if(!fread(&idx,sizeof(idxrec_t),1,smb->sid_fp)) {
508: sprintf(smb->last_error,"reading index");
509: return(1);
510: }
511: if(bot==top-1 && idx.number!=msg->hdr.number) {
512: sprintf(smb->last_error,"msg %d not found",msg->hdr.number);
513: return(1);
514: }
515: if(idx.number>msg->hdr.number) {
516: top=l;
517: l=bot+((top-bot)/2);
518: continue;
519: }
520: if(idx.number<msg->hdr.number) {
521: bot=l;
522: l=top-((top-bot)/2);
523: continue;
524: }
525: break;
526: }
527: msg->idx=idx;
528: msg->offset=l;
529: return(0);
530: }
531:
532: /****************************************************************************/
533: /* Reads the last index record in the open message base */
534: /****************************************************************************/
535: int SMBCALL smb_getlastidx(smb_t* smb, idxrec_t *idx)
536: {
537: long length;
538:
539: clearerr(smb->sid_fp);
540: length=filelength(fileno(smb->sid_fp));
541: if(length<sizeof(idxrec_t)) {
542: sprintf(smb->last_error,"invalid index file length: %ld",length);
543: return(-1);
544: }
545: fseek(smb->sid_fp,length-sizeof(idxrec_t),SEEK_SET);
546: if(!fread(idx,sizeof(idxrec_t),1,smb->sid_fp)) {
547: sprintf(smb->last_error,"reading index");
548: return(-2);
549: }
550: return(0);
551: }
552:
553: /****************************************************************************/
554: /* Figures out the total length of the header record for 'msg' */
555: /* Returns length */
556: /****************************************************************************/
557: uint SMBCALL smb_getmsghdrlen(smbmsg_t* msg)
558: {
559: int i;
560:
561: /* fixed portion */
562: msg->hdr.length=sizeof(msghdr_t);
563: /* data fields */
564: msg->hdr.length+=msg->hdr.total_dfields*sizeof(dfield_t);
565: /* header fields */
566: for(i=0;i<msg->total_hfields;i++) {
567: msg->hdr.length+=sizeof(hfield_t);
568: msg->hdr.length+=msg->hfield[i].length;
569: }
570: return(msg->hdr.length);
571: }
572:
573: /****************************************************************************/
574: /* Figures out the total length of the data buffer for 'msg' */
575: /* Returns length */
576: /****************************************************************************/
577: ulong SMBCALL smb_getmsgdatlen(smbmsg_t* msg)
578: {
579: int i;
580: ulong length=0L;
581:
582: for(i=0;i<msg->hdr.total_dfields;i++)
583: length+=msg->dfield[i].length;
584: return(length);
585: }
586:
587: /****************************************************************************/
588: /* Read header information into 'msg' structure */
589: /* msg->idx.offset must be set before calling this function */
590: /* Must call smb_freemsgmem() to free memory allocated for var len strs */
591: /* Returns 0 on success, non-zero if error */
592: /****************************************************************************/
593: int SMBCALL smb_getmsghdr(smb_t* smb, smbmsg_t* msg)
594: {
595: void *vp,**vpp;
596: ushort i;
597: ulong l,offset;
598: idxrec_t idx;
599:
600: rewind(smb->shd_fp);
601: fseek(smb->shd_fp,msg->idx.offset,SEEK_SET);
602: idx=msg->idx;
603: offset=msg->offset;
604: memset(msg,0,sizeof(smbmsg_t));
605: msg->idx=idx;
606: msg->offset=offset;
607: if(!fread(&msg->hdr,sizeof(msghdr_t),1,smb->shd_fp)) {
608: sprintf(smb->last_error,"reading msg header");
609: return(-1);
610: }
611: if(memcmp(msg->hdr.id,"SHD\x1a",4)) {
612: sprintf(smb->last_error,"corrupt header id: %.4s",msg->hdr.id);
613: return(-2);
614: }
615: if(msg->hdr.version<0x110) {
616: sprintf(smb->last_error,"insufficient header version: %X",msg->hdr.version);
617: return(-9);
618: }
619: l=sizeof(msghdr_t);
620: if(msg->hdr.total_dfields && (msg->dfield
621: =(dfield_t *)MALLOC(sizeof(dfield_t)*msg->hdr.total_dfields))==NULL) {
622: smb_freemsgmem(msg);
623: sprintf(smb->last_error,"malloc failure of %d bytes for %d data fields"
624: ,sizeof(dfield_t)*msg->hdr.total_dfields, msg->hdr.total_dfields);
625: return(-3);
626: }
627: i=0;
628: while(i<msg->hdr.total_dfields && l<msg->hdr.length) {
629: if(!fread(&msg->dfield[i],sizeof(dfield_t),1,smb->shd_fp)) {
630: smb_freemsgmem(msg);
631: sprintf(smb->last_error,"reading data field %d",i);
632: return(-4);
633: }
634: i++;
635: l+=sizeof(dfield_t);
636: }
637: if(i<msg->hdr.total_dfields) {
638: smb_freemsgmem(msg);
639: sprintf(smb->last_error,"insufficient data fields read (%d instead of %d)"
640: ,i,msg->hdr.total_dfields);
641: return(-8);
642: }
643: while(l<msg->hdr.length) {
644: i=msg->total_hfields;
645: if((vpp=(void* *)REALLOC(msg->hfield_dat,sizeof(void* )*(i+1)))==NULL) {
646: smb_freemsgmem(msg);
647: sprintf(smb->last_error
648: ,"realloc failure of %d bytes for header field data"
649: ,sizeof(void*)*(i+1));
650: return(-3);
651: }
652: msg->hfield_dat=vpp;
653: if((vp=(hfield_t *)REALLOC(msg->hfield,sizeof(hfield_t)*(i+1)))==NULL) {
654: smb_freemsgmem(msg);
655: sprintf(smb->last_error
656: ,"realloc failure of %d bytes for header fields"
657: ,sizeof(hfield_t)*(i+1));
658: return(-3);
659: }
660: msg->hfield=vp;
661: msg->total_hfields++;
662: if(!fread(&msg->hfield[i],sizeof(hfield_t),1,smb->shd_fp)) {
663: smb_freemsgmem(msg);
664: sprintf(smb->last_error,"reading header field");
665: return(-5);
666: }
667: l+=sizeof(hfield_t);
668: if((msg->hfield_dat[i]=(char*)MALLOC(msg->hfield[i].length+1))
669: ==NULL) { /* Allocate 1 extra for NULL terminator */
670: sprintf(smb->last_error
671: ,"malloc failure of %d bytes for header field %d"
672: ,msg->hfield[i].length+1, i);
673: smb_freemsgmem(msg); /* or 0 length field */
674: return(-3);
675: }
676: memset(msg->hfield_dat[i],0,msg->hfield[i].length+1); /* init to NULL */
677: if(msg->hfield[i].length
678: && !fread(msg->hfield_dat[i],msg->hfield[i].length,1,smb->shd_fp)) {
679: smb_freemsgmem(msg);
680: sprintf(smb->last_error,"reading header field data");
681: return(-6);
682: }
683: switch(msg->hfield[i].type) { /* convenience variables */
684: case SENDER:
685: if(!msg->from) {
686: msg->from=msg->hfield_dat[i];
687: break;
688: }
689: case FORWARDED: /* fall through */
690: msg->forwarded=1;
691: break;
692: case SENDERAGENT:
693: if(!msg->forwarded)
694: msg->from_agent=*(ushort *)msg->hfield_dat[i];
695: break;
696: case SENDEREXT:
697: if(!msg->forwarded)
698: msg->from_ext=msg->hfield_dat[i];
699: break;
700: case SENDERNETTYPE:
701: if(!msg->forwarded)
702: msg->from_net.type=*(ushort *)msg->hfield_dat[i];
703: break;
704: case SENDERNETADDR:
705: if(!msg->forwarded)
706: msg->from_net.addr=msg->hfield_dat[i];
707: break;
708: case REPLYTO:
709: msg->replyto=msg->hfield_dat[i];
710: break;
711: case REPLYTOEXT:
712: msg->replyto_ext=msg->hfield_dat[i];
713: break;
714: case REPLYTOAGENT:
715: msg->replyto_agent=*(ushort *)msg->hfield_dat[i];
716: break;
717: case REPLYTONETTYPE:
718: msg->replyto_net.type=*(ushort *)msg->hfield_dat[i];
719: break;
720: case REPLYTONETADDR:
721: msg->replyto_net.addr=msg->hfield_dat[i];
722: break;
723: case RECIPIENT:
724: msg->to=msg->hfield_dat[i];
725: break;
726: case RECIPIENTEXT:
727: msg->to_ext=msg->hfield_dat[i];
728: break;
729: case RECIPIENTAGENT:
730: msg->to_agent=*(ushort *)msg->hfield_dat[i];
731: break;
732: case RECIPIENTNETTYPE:
733: msg->to_net.type=*(ushort *)msg->hfield_dat[i];
734: break;
735: case RECIPIENTNETADDR:
736: msg->to_net.addr=msg->hfield_dat[i];
737: break;
738: case SUBJECT:
739: msg->subj=msg->hfield_dat[i];
740: break;
741: }
742: l+=msg->hfield[i].length;
743: }
744:
745: if(!msg->from || !msg->to || !msg->subj) {
746: sprintf(smb->last_error,"missing required header field (from/to/subj)");
747: smb_freemsgmem(msg);
748: return(-7);
749: }
750: return(0);
751: }
752:
753: /****************************************************************************/
754: /* Frees memory allocated for 'msg' */
755: /****************************************************************************/
756: void SMBCALL smb_freemsgmem(smbmsg_t* msg)
757: {
758: ushort i;
759:
760: if(msg->dfield) {
761: FREE(msg->dfield);
762: msg->dfield=NULL;
763: }
764: for(i=0;i<msg->total_hfields;i++)
765: if(msg->hfield_dat[i]) {
766: FREE(msg->hfield_dat[i]);
767: msg->hfield_dat[i]=NULL;
768: }
769: msg->total_hfields=0;
770: if(msg->hfield) {
771: FREE(msg->hfield);
772: msg->hfield=NULL;
773: }
774: if(msg->hfield_dat) {
775: FREE(msg->hfield_dat);
776: msg->hfield_dat=NULL;
777: }
778: }
779:
780: /****************************************************************************/
781: /* Copies memory allocated for 'srcmsg' to 'msg' */
782: /****************************************************************************/
783: int SMBCALL smb_copymsgmem(smbmsg_t* msg, smbmsg_t* srcmsg)
784: {
785: int i;
786:
787: memcpy(msg,srcmsg,sizeof(smbmsg_t));
788:
789: /* data field types/lengths */
790: if((msg->dfield=MALLOC(msg->hdr.total_dfields*sizeof(dfield_t)))==NULL)
791: return(1);
792: memcpy(msg->dfield,srcmsg->dfield,msg->hdr.total_dfields*sizeof(dfield_t));
793:
794: /* header field types/lengths */
795: if((msg->hfield=MALLOC(msg->total_hfields*sizeof(hfield_t)))==NULL)
796: return(2);
797: memcpy(msg->hfield,srcmsg->hfield,msg->total_hfields*sizeof(hfield_t));
798:
799: /* header field data */
800: if((msg->hfield_dat=MALLOC(msg->total_hfields*sizeof(void*)))==NULL)
801: return(3);
802:
803: for(i=0;i<msg->total_hfields;i++) {
804: if((msg->hfield_dat[i]=(char*)MALLOC(msg->hfield[i].length))==NULL)
805: return(4);
806: memcpy(msg->hfield_dat[i],srcmsg->hfield_dat[i],msg->hfield[i].length);
807: }
808:
809: return(0);
810: }
811:
812: /****************************************************************************/
813: /* Unlocks header for 'msg' */
814: /****************************************************************************/
815: int SMBCALL smb_unlockmsghdr(smb_t* smb, smbmsg_t* msg)
816: {
817: return(unlock(fileno(smb->shd_fp),msg->idx.offset,sizeof(msghdr_t)));
818: }
819:
820:
821: /****************************************************************************/
822: /* Adds a header field to the 'msg' structure (in memory only) */
823: /****************************************************************************/
824: int SMBCALL smb_hfield(smbmsg_t* msg, ushort type, ushort length, void* data)
825: {
826: void* vp,**vpp;
827: int i;
828:
829: i=msg->total_hfields;
830: if((vp=(hfield_t *)REALLOC(msg->hfield,sizeof(hfield_t)*(i+1)))==NULL)
831: return(1);
832:
833: msg->hfield=vp;
834: if((vpp=(void* *)REALLOC(msg->hfield_dat,sizeof(void* )*(i+1)))==NULL)
835: return(2);
836:
837: msg->hfield_dat=vpp;
838: msg->total_hfields++;
839: msg->hfield[i].type=type;
840: msg->hfield[i].length=length;
841: if(length) {
842: if((msg->hfield_dat[i]=(void* )MALLOC(length))==NULL)
843: return(4);
844: memcpy(msg->hfield_dat[i],data,length);
845: }
846: else
847: msg->hfield_dat[i]=NULL;
848: return(0);
849: }
850:
851: /****************************************************************************/
852: /* Adds a data field to the 'msg' structure (in memory only) */
853: /* Automatically figures out the offset into the data buffer from existing */
854: /* dfield lengths */
855: /****************************************************************************/
856: int SMBCALL smb_dfield(smbmsg_t* msg, ushort type, ulong length)
857: {
858: void* vp;
859: int i,j;
860:
861: i=msg->hdr.total_dfields;
862: if((vp=(dfield_t *)REALLOC(msg->dfield,sizeof(dfield_t)*(i+1)))==NULL)
863: return(1);
864:
865: msg->dfield=vp;
866: msg->hdr.total_dfields++;
867: msg->dfield[i].type=type;
868: msg->dfield[i].length=length;
869: for(j=msg->dfield[i].offset=0;j<i;j++)
870: msg->dfield[i].offset+=msg->dfield[j].length;
871: return(0);
872: }
873:
874: /****************************************************************************/
875: /* Checks CRC history file for duplicate crc. If found, returns 1. */
876: /* If no dupe, adds to CRC history and returns 0, or negative if error. */
877: /****************************************************************************/
878: int SMBCALL smb_addcrc(smb_t* smb, ulong crc)
879: {
880: char str[128];
881: int file;
882: long length;
883: ulong l,*buf;
884: ulong start=0;
885:
886: if(!smb->status.max_crcs)
887: return(0);
888:
889: sprintf(str,"%s.sch",smb->file);
890: while(1) {
891: if((file=sopen(str,O_RDWR|O_CREAT|O_BINARY,SH_DENYRW))!=-1)
892: break;
893: if(errno!=EACCES) {
894: sprintf(smb->last_error,"%d opening %s", errno, str);
895: return(-1);
896: }
897: if(!start)
898: start=time(NULL);
899: else
900: if(time(NULL)-start>=smb->retry_time) {
901: sprintf(smb->last_error,"timeout opening %s", str);
902: return(-2);
903: }
904: }
905:
906: length=filelength(file);
907: if(length<0L) {
908: close(file);
909: sprintf(smb->last_error,"invalid file length: %ld", length);
910: return(-4);
911: }
912: if((buf=(ulong*)MALLOC(smb->status.max_crcs*4))==NULL) {
913: close(file);
914: sprintf(smb->last_error
915: ,"malloc failure of %d bytes"
916: ,smb->status.max_crcs*4);
917: return(-3);
918: }
919: if((ulong)length>=smb->status.max_crcs*4L) { /* Reached or exceeds max crcs */
920: read(file,buf,smb->status.max_crcs*4);
921: for(l=0;l<smb->status.max_crcs;l++)
922: if(crc==buf[l])
923: break;
924: if(l<smb->status.max_crcs) { /* Dupe CRC found */
925: close(file);
926: FREE(buf);
927: return(1);
928: }
929: chsize(file,0L); /* truncate it */
930: lseek(file,0L,SEEK_SET);
931: write(file,buf+4,(smb->status.max_crcs-1)*4);
932: }
933:
934: else if(length/4) { /* Less than max crcs */
935: read(file,buf,length);
936: for(l=0;l<(ulong)(length/4);l++)
937: if(crc==buf[l])
938: break;
939: if(l<(ulong)(length/4L)) { /* Dupe CRC found */
940: close(file);
941: FREE(buf);
942: return(1);
943: }
944: }
945:
946: lseek(file,0L,SEEK_END);
947: write(file,&crc,4); /* Write to the end */
948: FREE(buf);
949: close(file);
950: return(0);
951: }
952:
953: /****************************************************************************/
954: /* Creates a new message header record in the header file. */
955: /* If storage is SMB_SELFPACK, self-packing conservative allocation is used */
956: /* If storage is SMB_FASTALLOC, fast allocation is used */
957: /* If storage is SMB_HYPERALLOC, no allocation tables are used (fastest) */
958: /****************************************************************************/
959: int SMBCALL smb_addmsghdr(smb_t* smb, smbmsg_t* msg, int storage)
960: {
961: int i;
962: long l;
963:
964: if(smb_locksmbhdr(smb))
965: return(1);
966: if(smb_getstatus(smb))
967: return(2);
968:
969: if(storage!=SMB_HYPERALLOC && (i=smb_open_ha(smb))!=0)
970: return(i);
971:
972: msg->hdr.length=smb_getmsghdrlen(msg);
973: if(storage==SMB_HYPERALLOC)
974: l=smb_hallochdr(smb);
975: else if(storage==SMB_FASTALLOC)
976: l=smb_fallochdr(smb,msg->hdr.length);
977: else
978: l=smb_allochdr(smb,msg->hdr.length);
979: if(l==-1L) {
980: smb_unlocksmbhdr(smb);
981: smb_close_ha(smb);
982: return(-1);
983: }
984:
985: smb->status.last_msg++;
986: msg->idx.number=msg->hdr.number=smb->status.last_msg;
987: msg->idx.offset=smb->status.header_offset+l;
988: msg->idx.time=msg->hdr.when_imported.time;
989: msg->idx.attr=msg->hdr.attr;
990: msg->offset=smb->status.total_msgs;
991: smb->status.total_msgs++;
992: smb_putstatus(smb);
993:
994: if(storage!=SMB_HYPERALLOC)
995: smb_close_ha(smb);
996: i=smb_putmsg(smb,msg);
997: smb_unlocksmbhdr(smb);
998: return(i);
999: }
1000:
1001: /****************************************************************************/
1002: /* Writes both header and index information for msg 'msg' */
1003: /****************************************************************************/
1004: int SMBCALL smb_putmsg(smb_t* smb, smbmsg_t* msg)
1005: {
1006: int i;
1007:
1008: i=smb_putmsghdr(smb,msg);
1009: if(i)
1010: return(i);
1011: return(smb_putmsgidx(smb,msg));
1012: }
1013:
1014: /****************************************************************************/
1015: /* Writes index information for 'msg' */
1016: /* msg->idx */
1017: /* and msg->offset must be set prior to calling to this function */
1018: /* Returns 0 if everything ok */
1019: /****************************************************************************/
1020: int SMBCALL smb_putmsgidx(smb_t* smb, smbmsg_t* msg)
1021: {
1022:
1023: clearerr(smb->sid_fp);
1024: fseek(smb->sid_fp,msg->offset*sizeof(idxrec_t),SEEK_SET);
1025: if(!fwrite(&msg->idx,sizeof(idxrec_t),1,smb->sid_fp)) {
1026: sprintf(smb->last_error,"writing index");
1027: return(1);
1028: }
1029: fflush(smb->sid_fp);
1030: return(0);
1031: }
1032:
1033: /****************************************************************************/
1034: /* Writes header information for 'msg' */
1035: /* msg->hdr.length */
1036: /* msg->idx.offset */
1037: /* and msg->offset must be set prior to calling to this function */
1038: /* Returns 0 if everything ok */
1039: /****************************************************************************/
1040: int SMBCALL smb_putmsghdr(smb_t* smb, smbmsg_t* msg)
1041: {
1042: ushort i;
1043: ulong l;
1044:
1045: clearerr(smb->shd_fp);
1046: if(fseek(smb->shd_fp,msg->idx.offset,SEEK_SET)) {
1047: sprintf(smb->last_error,"seeking to %d in index",msg->idx.offset);
1048: return(-1);
1049: }
1050:
1051: /************************************************/
1052: /* Write the fixed portion of the header record */
1053: /************************************************/
1054: if(!fwrite(&msg->hdr,sizeof(msghdr_t),1,smb->shd_fp)) {
1055: sprintf(smb->last_error,"writing fixed portion of header record");
1056: return(-2);
1057: }
1058:
1059: /************************************************/
1060: /* Write the data fields (each is fixed length) */
1061: /************************************************/
1062: for(i=0;i<msg->hdr.total_dfields;i++)
1063: if(!fwrite(&msg->dfield[i],sizeof(dfield_t),1,smb->shd_fp)) {
1064: sprintf(smb->last_error,"writing data field");
1065: return(-3);
1066: }
1067:
1068: /*******************************************/
1069: /* Write the variable length header fields */
1070: /*******************************************/
1071: for(i=0;i<msg->total_hfields;i++) {
1072: if(!fwrite(&msg->hfield[i],sizeof(hfield_t),1,smb->shd_fp)) {
1073: sprintf(smb->last_error,"writing header field");
1074: return(-4);
1075: }
1076: if(msg->hfield[i].length /* more then 0 bytes long */
1077: && !fwrite(msg->hfield_dat[i],msg->hfield[i].length,1,smb->shd_fp)) {
1078: sprintf(smb->last_error,"writing header field data");
1079: return(-5);
1080: }
1081: }
1082:
1083: l=smb_getmsghdrlen(msg);
1084: while(l%SHD_BLOCK_LEN) {
1085: if(fputc(0,smb->shd_fp)==EOF) {
1086: sprintf(smb->last_error,"padding header block");
1087: return(-6); /* pad block with NULL */
1088: }
1089: l++;
1090: }
1091: fflush(smb->shd_fp);
1092: return(0);
1093: }
1094:
1095: /****************************************************************************/
1096: /* Creates a sub-board's initial header file */
1097: /* Truncates and deletes other associated SMB files */
1098: /****************************************************************************/
1099: int SMBCALL smb_create(smb_t* smb)
1100: {
1101: char str[128];
1102: smbhdr_t hdr;
1103:
1104: if(filelength(fileno(smb->shd_fp))>=sizeof(smbhdr_t)+sizeof(smbstatus_t)
1105: && smb_locksmbhdr(smb)) /* header exists, so lock it */
1106: return(1);
1107: memset(&hdr,0,sizeof(smbhdr_t));
1108: memcpy(hdr.id,"SMB\x1a",4); /* <S> <M> <B> <^Z> */
1109: hdr.version=SMB_VERSION;
1110: hdr.length=sizeof(smbhdr_t)+sizeof(smbstatus_t);
1111: smb->status.last_msg=smb->status.total_msgs=0;
1112: smb->status.header_offset=sizeof(smbhdr_t)+sizeof(smbstatus_t);
1113: rewind(smb->shd_fp);
1114: fwrite(&hdr,1,sizeof(smbhdr_t),smb->shd_fp);
1115: fwrite(&(smb->status),1,sizeof(smbstatus_t),smb->shd_fp);
1116: rewind(smb->shd_fp);
1117: chsize(fileno(smb->shd_fp),sizeof(smbhdr_t)+sizeof(smbstatus_t));
1118: fflush(smb->shd_fp);
1119:
1120: rewind(smb->sdt_fp);
1121: chsize(fileno(smb->sdt_fp),0L);
1122: rewind(smb->sid_fp);
1123: chsize(fileno(smb->sid_fp),0L);
1124:
1125: sprintf(str,"%s.sda",smb->file);
1126: remove(str); /* if it exists, delete it */
1127: sprintf(str,"%s.sha",smb->file);
1128: remove(str); /* if it exists, delete it */
1129: sprintf(str,"%s.sch",smb->file);
1130: remove(str);
1131: smb_unlocksmbhdr(smb);
1132: return(0);
1133: }
1134:
1135: /****************************************************************************/
1136: /* Returns number of data blocks required to store "length" amount of data */
1137: /****************************************************************************/
1138: ulong SMBCALL smb_datblocks(ulong length)
1139: {
1140: ulong blocks;
1141:
1142: blocks=length/SDT_BLOCK_LEN;
1143: if(length%SDT_BLOCK_LEN)
1144: blocks++;
1145: return(blocks);
1146: }
1147:
1148: /****************************************************************************/
1149: /* Returns number of header blocks required to store "length" size header */
1150: /****************************************************************************/
1151: ulong SMBCALL smb_hdrblocks(ulong length)
1152: {
1153: ulong blocks;
1154:
1155: blocks=length/SHD_BLOCK_LEN;
1156: if(length%SHD_BLOCK_LEN)
1157: blocks++;
1158: return(blocks);
1159: }
1160:
1161: /****************************************************************************/
1162: /* Finds unused space in data file based on block allocation table and */
1163: /* marks space as used in allocation table. */
1164: /* File must be opened read/write DENY ALL */
1165: /* Returns offset to beginning of data (in bytes, not blocks) */
1166: /* Assumes smb_open_da() has been called */
1167: /* smb_close_da() should be called after */
1168: /* Returns negative on error */
1169: /****************************************************************************/
1170: long SMBCALL smb_allocdat(smb_t* smb, ulong length, ushort headers)
1171: {
1172: ushort i,j;
1173: ulong l,blocks,offset=0L;
1174:
1175: blocks=smb_datblocks(length);
1176: j=0; /* j is consecutive unused block counter */
1177: fflush(smb->sda_fp);
1178: rewind(smb->sda_fp);
1179: while(!feof(smb->sda_fp)) {
1180: if(!fread(&i,2,1,smb->sda_fp))
1181: break;
1182: offset+=SDT_BLOCK_LEN;
1183: if(!i) j++;
1184: else j=0;
1185: if(j==blocks) {
1186: offset-=(blocks*SDT_BLOCK_LEN);
1187: break;
1188: }
1189: }
1190: clearerr(smb->sda_fp);
1191: fseek(smb->sda_fp,(offset/SDT_BLOCK_LEN)*2L,SEEK_SET);
1192: for(l=0;l<blocks;l++)
1193: if(!fwrite(&headers,2,1,smb->sda_fp)) {
1194: sprintf(smb->last_error,"writing allocation bytes");
1195: return(-1);
1196: }
1197: fflush(smb->sda_fp);
1198: return(offset);
1199: }
1200:
1201: /****************************************************************************/
1202: /* Allocates space for data, but doesn't search for unused blocks */
1203: /* Returns negative on error */
1204: /****************************************************************************/
1205: long SMBCALL smb_fallocdat(smb_t* smb, ulong length, ushort headers)
1206: {
1207: ulong l,blocks,offset;
1208:
1209: fflush(smb->sda_fp);
1210: clearerr(smb->sda_fp);
1211: blocks=smb_datblocks(length);
1212: fseek(smb->sda_fp,0L,SEEK_END);
1213: offset=(ftell(smb->sda_fp)/2L)*SDT_BLOCK_LEN;
1214: for(l=0;l<blocks;l++)
1215: if(!fwrite(&headers,2,1,smb->sda_fp))
1216: break;
1217: fflush(smb->sda_fp);
1218: if(l<blocks) {
1219: sprintf(smb->last_error,"writing allocation bytes");
1220: return(-1L);
1221: }
1222: return(offset);
1223: }
1224:
1225: /****************************************************************************/
1226: /* De-allocates space for data */
1227: /* Returns non-zero on error */
1228: /****************************************************************************/
1229: int SMBCALL smb_freemsgdat(smb_t* smb, ulong offset, ulong length
1230: , ushort headers)
1231: {
1232: int da_opened=0;
1233: ushort i;
1234: ulong l,blocks;
1235:
1236: blocks=smb_datblocks(length);
1237:
1238: if(smb->sda_fp==NULL) {
1239: if((i=smb_open_da(smb))!=0)
1240: return(i);
1241: da_opened=1;
1242: }
1243:
1244: clearerr(smb->sda_fp);
1245: for(l=0;l<blocks;l++) {
1246: if(fseek(smb->sda_fp,((offset/SDT_BLOCK_LEN)+l)*2L,SEEK_SET)) {
1247: sprintf(smb->last_error
1248: ,"seeking to %ld of allocation file"
1249: ,((offset/SDT_BLOCK_LEN)+l)*2L);
1250: return(1);
1251: }
1252: if(!fread(&i,2,1,smb->sda_fp)) {
1253: sprintf(smb->last_error,"reading allocation bytes");
1254: return(2);
1255: }
1256: if(headers>i)
1257: i=0; /* don't want to go negative */
1258: else
1259: i-=headers;
1260: if(fseek(smb->sda_fp,-2L,SEEK_CUR)) {
1261: sprintf(smb->last_error,"seeking backwards 2 bytes in allocation file");
1262: return(3);
1263: }
1264: if(!fwrite(&i,2,1,smb->sda_fp)) {
1265: sprintf(smb->last_error,"writing allocation bytes");
1266: return(4);
1267: }
1268: }
1269: fflush(smb->sda_fp);
1270: if(da_opened)
1271: smb_close_da(smb);
1272: return(0);
1273: }
1274:
1275: /****************************************************************************/
1276: /* Adds to data allocation records for blocks starting at 'offset' */
1277: /* Returns non-zero on error */
1278: /****************************************************************************/
1279: int SMBCALL smb_incdat(smb_t* smb, ulong offset, ulong length, ushort headers)
1280: {
1281: ushort i;
1282: ulong l,blocks;
1283:
1284: clearerr(smb->sda_fp);
1285: blocks=smb_datblocks(length);
1286: for(l=0;l<blocks;l++) {
1287: fseek(smb->sda_fp,((offset/SDT_BLOCK_LEN)+l)*2L,SEEK_SET);
1288: if(!fread(&i,2,1,smb->sda_fp)) {
1289: sprintf(smb->last_error,"reading allocation record");
1290: return(1);
1291: }
1292: i+=headers;
1293: fseek(smb->sda_fp,-2L,SEEK_CUR);
1294: if(!fwrite(&i,2,1,smb->sda_fp)) {
1295: sprintf(smb->last_error,"writing allocation record");
1296: return(2);
1297: }
1298: }
1299: fflush(smb->sda_fp);
1300: return(0);
1301: }
1302:
1303: /****************************************************************************/
1304: /* De-allocates blocks for header record */
1305: /* Returns non-zero on error */
1306: /****************************************************************************/
1307: int SMBCALL smb_freemsghdr(smb_t* smb, ulong offset, ulong length)
1308: {
1309: uchar c=0;
1310: ulong l,blocks;
1311:
1312: clearerr(smb->sha_fp);
1313: blocks=smb_hdrblocks(length);
1314: fseek(smb->sha_fp,offset/SHD_BLOCK_LEN,SEEK_SET);
1315: for(l=0;l<blocks;l++)
1316: if(!fwrite(&c,1,1,smb->sha_fp)) {
1317: sprintf(smb->last_error,"writing allocation record");
1318: return(1);
1319: }
1320: fflush(smb->sha_fp);
1321: return(0);
1322: }
1323:
1324: /****************************************************************************/
1325: /* Frees all allocated header and data blocks for 'msg' */
1326: /****************************************************************************/
1327: int SMBCALL smb_freemsg(smb_t* smb, smbmsg_t* msg)
1328: {
1329: int i;
1330: ushort x;
1331:
1332: if(smb->status.attr&SMB_HYPERALLOC) /* Nothing to do */
1333: return(0);
1334:
1335: for(x=0;x<msg->hdr.total_dfields;x++) {
1336: if((i=smb_freemsgdat(smb,msg->hdr.offset+msg->dfield[x].offset
1337: ,msg->dfield[x].length,1))!=0)
1338: return(i);
1339: }
1340: return(smb_freemsghdr(smb,msg->idx.offset-smb->status.header_offset
1341: ,msg->hdr.length));
1342: }
1343:
1344: /****************************************************************************/
1345: /* Finds unused space in header file based on block allocation table and */
1346: /* marks space as used in allocation table. */
1347: /* File must be opened read/write DENY ALL */
1348: /* Returns offset to beginning of header (in bytes, not blocks) */
1349: /* Assumes smb_open_ha() has been called */
1350: /* smb_close_ha() should be called after */
1351: /* Returns -1L on error */
1352: /****************************************************************************/
1353: long SMBCALL smb_allochdr(smb_t* smb, ulong length)
1354: {
1355: uchar c;
1356: ushort i;
1357: ulong l,blocks,offset=0;
1358:
1359: blocks=smb_hdrblocks(length);
1360: i=0; /* i is consecutive unused block counter */
1361: fflush(smb->sha_fp);
1362: rewind(smb->sha_fp);
1363: while(!feof(smb->sha_fp)) {
1364: if(!fread(&c,1,1,smb->sha_fp))
1365: break;
1366: offset+=SHD_BLOCK_LEN;
1367: if(!c) i++;
1368: else i=0;
1369: if(i==blocks) {
1370: offset-=(blocks*SHD_BLOCK_LEN);
1371: break;
1372: }
1373: }
1374: clearerr(smb->sha_fp);
1375: fseek(smb->sha_fp,offset/SHD_BLOCK_LEN,SEEK_SET);
1376: c=1;
1377: for(l=0;l<blocks;l++)
1378: if(!fwrite(&c,1,1,smb->sha_fp)) {
1379: sprintf(smb->last_error,"writing allocation record");
1380: return(-1L);
1381: }
1382: fflush(smb->sha_fp);
1383: return(offset);
1384: }
1385:
1386: /****************************************************************************/
1387: /* Allocates space for index, but doesn't search for unused blocks */
1388: /* Returns -1L on error */
1389: /****************************************************************************/
1390: long SMBCALL smb_fallochdr(smb_t* smb, ulong length)
1391: {
1392: uchar c=1;
1393: ulong l,blocks,offset;
1394:
1395: blocks=smb_hdrblocks(length);
1396: fflush(smb->sha_fp);
1397: clearerr(smb->sha_fp);
1398: fseek(smb->sha_fp,0L,SEEK_END);
1399: offset=ftell(smb->sha_fp)*SHD_BLOCK_LEN;
1400: for(l=0;l<blocks;l++)
1401: if(!fwrite(&c,1,1,smb->sha_fp)) {
1402: sprintf(smb->last_error,"writing allocation record");
1403: return(-1L);
1404: }
1405: fflush(smb->sha_fp);
1406: return(offset);
1407: }
1408:
1409: /************************************************************************/
1410: /* Allocate header blocks using Hyper Allocation */
1411: /* this function should be most likely not be called from anywhere but */
1412: /* smb_addmsghdr() */
1413: /************************************************************************/
1414: long SMBCALL smb_hallochdr(smb_t* smb)
1415: {
1416: ulong l;
1417:
1418: fflush(smb->shd_fp);
1419: fseek(smb->shd_fp,0L,SEEK_END);
1420: l=ftell(smb->shd_fp);
1421: if(l<smb->status.header_offset) /* Header file truncated?!? */
1422: return(smb->status.header_offset);
1423: while((l-smb->status.header_offset)%SHD_BLOCK_LEN) /* Even block boundry */
1424: l++;
1425: return(l-smb->status.header_offset);
1426: }
1427:
1428: /************************************************************************/
1429: /* Allocate data blocks using Hyper Allocation */
1430: /* smb_locksmbhdr() should be called before this function and not */
1431: /* unlocked until all data fields for this message have been written */
1432: /* to the SDT file */
1433: /************************************************************************/
1434: long SMBCALL smb_hallocdat(smb_t* smb)
1435: {
1436: long l;
1437:
1438: fflush(smb->sdt_fp);
1439: fseek(smb->sdt_fp,0L,SEEK_END);
1440: l=ftell(smb->sdt_fp);
1441: if(l<=0)
1442: return(l);
1443: while(l%SDT_BLOCK_LEN) /* Make sure even block boundry */
1444: l++;
1445: return(l);
1446: }
1447:
1448:
1449: int SMBCALL smb_feof(FILE* fp)
1450: {
1451: return(feof(fp));
1452: }
1453:
1454: int SMBCALL smb_ferror(FILE* fp)
1455: {
1456: return(ferror(fp));
1457: }
1458:
1459: int SMBCALL smb_fflush(FILE* fp)
1460: {
1461: return(fflush(fp));
1462: }
1463:
1464: int SMBCALL smb_fgetc(FILE* fp)
1465: {
1466: return(fgetc(fp));
1467: }
1468:
1469: int SMBCALL smb_fputc(int ch, FILE* fp)
1470: {
1471: return(fputc(ch,fp));
1472: }
1473:
1474: int SMBCALL smb_fseek(FILE* fp, long offset, int whence)
1475: {
1476: return(fseek(fp,offset,whence));
1477: }
1478:
1479: long SMBCALL smb_ftell(FILE* fp)
1480: {
1481: return(ftell(fp));
1482: }
1483:
1484: long SMBCALL smb_fgetlength(FILE* fp)
1485: {
1486: return(filelength(fileno(fp)));
1487: }
1488:
1489: int SMBCALL smb_fsetlength(FILE* fp, long length)
1490: {
1491: return(chsize(fileno(fp),length));
1492: }
1493:
1494: void SMBCALL smb_rewind(FILE* fp)
1495: {
1496: rewind(fp);
1497: }
1498:
1499: void SMBCALL smb_clearerr(FILE* fp)
1500: {
1501: clearerr(fp);
1502: }
1503:
1504: long SMBCALL smb_fread(void HUGE16* buf, long bytes, FILE* fp)
1505: {
1506: #ifdef __FLAT__
1507: return(fread(buf,1,bytes,fp));
1508: #else
1509: long count;
1510:
1511: for(count=bytes;count>0x7fff;count-=0x7fff,(char*)buf+=0x7fff)
1512: if(fread((char*)buf,1,0x7fff,fp)!=0x7fff)
1513: return(bytes-count);
1514: if(fread((char*)buf,1,(size_t)count,fp)!=(size_t)count)
1515: return(bytes-count);
1516: return(bytes);
1517: #endif
1518: }
1519:
1520: long SMBCALL smb_fwrite(void HUGE16* buf, long bytes, FILE* fp)
1521: {
1522: #ifdef __FLAT__
1523: return(fwrite(buf,1,bytes,fp));
1524: #else
1525: long count;
1526:
1527: for(count=bytes;count>0x7fff;count-=0x7fff,(char*)buf+=0x7fff)
1528: if(fwrite((char*)buf,1,0x7fff,fp)!=0x7fff)
1529: return(bytes-count);
1530: if(fwrite((char*)buf,1,(size_t)count,fp)!=(size_t)count)
1531: return(bytes-count);
1532: return(bytes);
1533: #endif
1534: }
1535:
1536: /* End of SMBLIB.C */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.