|
|
1.1 root 1: /* SMBLIB.C */
2:
3: #include "smblib.h"
4:
5: /****************************************************************************/
6: /* Open a message base of name 'smb_file' */
7: /* If retry_time is 0, fast open method (no compatibility/validity check) */
8: /* Opens files for READing messages or updating message indices only */
9: /****************************************************************************/
10: int smb_open(int retry_time)
11: {
12: int file;
13: char str[128];
14: smbhdr_t hdr;
15:
16: shd_fp=sdt_fp=sid_fp=NULL;
17: sprintf(str,"%s.SHD",smb_file);
18: if((file=sopen(str,O_RDWR|O_CREAT|O_BINARY,SH_DENYNO,S_IWRITE|S_IREAD))==-1
19: || (shd_fp=fdopen(file,"r+b"))==NULL) {
20: if(file!=-1)
21: close(file);
22: return(2); }
23:
24: if(retry_time && filelength(file)>=sizeof(smbhdr_t)) {
25: setvbuf(shd_fp,shd_buf,_IONBF,SHD_BLOCK_LEN);
26: if(smb_locksmbhdr(retry_time)) {
27: smb_close();
28: return(-1); }
29: memset(&hdr,0,sizeof(smbhdr_t));
30: fread(&hdr,sizeof(smbhdr_t),1,shd_fp);
31: if(memcmp(hdr.id,"SMB\x1a",4)) {
32: smb_close();
33: return(-2); }
34: if(hdr.version<0x110) { /* Compatibility check */
35: smb_close();
36: return(-3); }
37: smb_unlocksmbhdr();
38: rewind(shd_fp); }
39:
40: setvbuf(shd_fp,shd_buf,_IOFBF,SHD_BLOCK_LEN);
41:
42: sprintf(str,"%s.SDT",smb_file);
43: if((file=sopen(str,O_RDWR|O_CREAT|O_BINARY,SH_DENYNO,S_IWRITE|S_IREAD))==-1
44: || (sdt_fp=fdopen(file,"r+b"))==NULL) {
45: if(file!=-1)
46: close(file);
47: smb_close();
48: return(1); }
49: setvbuf(sdt_fp,NULL,_IOFBF,2*1024);
50:
51: sprintf(str,"%s.SID",smb_file);
52: if((file=sopen(str,O_RDWR|O_CREAT|O_BINARY,SH_DENYNO,S_IWRITE|S_IREAD))==-1
53: || (sid_fp=fdopen(file,"r+b"))==NULL) {
54: if(file!=-1)
55: close(file);
56: smb_close();
57: return(3); }
58: setvbuf(sid_fp,NULL,_IOFBF,2*1024);
59:
60: return(0);
61: }
62:
63: /****************************************************************************/
64: /* Closes the currently open message base */
65: /****************************************************************************/
66: void smb_close(void)
67: {
68: if(shd_fp!=NULL) {
69: smb_unlocksmbhdr(); /* In case it's been locked */
70: fclose(shd_fp); }
71: if(sid_fp!=NULL)
72: fclose(sid_fp);
73: if(sdt_fp!=NULL)
74: fclose(sdt_fp);
75: sid_fp=shd_fp=sdt_fp=NULL;
76: }
77:
78: /****************************************************************************/
79: /* Opens the data block allocation table message base 'smb_file' */
80: /* Retrys for retry_time number of seconds */
81: /* Return 0 on success, non-zero otherwise */
82: /****************************************************************************/
83: int smb_open_da(int retry_time)
84: {
85: int file;
86: char str[128];
87: long start;
88:
89: start=time(NULL);
90: sprintf(str,"%s.SDA",smb_file);
91: while(1) {
92: if((file=sopen(str,O_RDWR|O_CREAT|O_BINARY,SH_DENYRW,S_IWRITE|S_IREAD))!=-1)
93: break;
94: if(errno!=EACCES)
95: return(-1);
96: if(time(NULL)-start>=retry_time)
97: return(-2); }
98: if((sda_fp=fdopen(file,"r+b"))==NULL)
99: return(-3);
100: setvbuf(sda_fp,NULL,_IOFBF,2*1024);
101: return(0);
102: }
103:
104: /****************************************************************************/
105: /* Opens the header block allocation table for message base 'smb_file' */
106: /* Retrys for retry_time number of seconds */
107: /* Return 0 on success, non-zero otherwise */
108: /****************************************************************************/
109: int smb_open_ha(int retry_time)
110: {
111: int file;
112: char str[128];
113: long start;
114:
115: start=time(NULL);
116: sprintf(str,"%s.SHA",smb_file);
117: while(1) {
118: if((file=sopen(str,O_RDWR|O_CREAT|O_BINARY,SH_DENYRW,S_IWRITE|S_IREAD))!=-1)
119: break;
120: if(errno!=EACCES)
121: return(-1);
122: if(time(NULL)-start>=retry_time)
123: return(-2); }
124: if((sha_fp=fdopen(file,"r+b"))==NULL)
125: return(-3);
126: setvbuf(sha_fp,NULL,_IOFBF,2*1024);
127: return(0);
128: }
129:
130: /****************************************************************************/
131: /* If the parameter 'push' is non-zero, this function stores the currently */
132: /* open message base to the "virtual" smb stack. Up to SMB_STACK_LEN */
133: /* message bases may be stored (defined in SMBDEFS.H). */
134: /* The parameter 'op' is the operation to perform on the stack. Either */
135: /* SMB_STACK_PUSH, SMB_STACK_POP, or SMB_STACK_XCHNG */
136: /* If the operation is SMB_STACK_POP, this function restores a message base */
137: /* previously saved with a SMB_STACK_PUSH call to this same function. */
138: /* If the operation is SMB_STACK_XCHNG, then the current message base is */
139: /* exchanged with the message base on the top of the stack (most recently */
140: /* pushed. */
141: /* If the current message base is not open, the SMB_STACK_PUSH and */
142: /* SMB_STACK_XCHNG operations do nothing */
143: /* Returns 0 on success, non-zero if stack full. */
144: /* If operation is SMB_STACK_POP or SMB_STACK_XCHNG, it always returns 0. */
145: /****************************************************************************/
146: int smb_stack(int op)
147: {
148: static char stack_file[SMB_STACK_LEN][128];
149: static FILE *stack_sdt[SMB_STACK_LEN],
150: *stack_shd[SMB_STACK_LEN],
151: *stack_sid[SMB_STACK_LEN],
152: *stack_sda[SMB_STACK_LEN],
153: *stack_sha[SMB_STACK_LEN];
154: static int stack_idx;
155: char tmp_file[128];
156: FILE *tmp_sdt,
157: *tmp_shd,
158: *tmp_sid,
159: *tmp_sda,
160: *tmp_sha;
161:
162: if(op==SMB_STACK_PUSH) {
163: if(stack_idx>=SMB_STACK_LEN)
164: return(1);
165: if(shd_fp==NULL || sdt_fp==NULL || sid_fp==NULL) /* Msg base not open */
166: return(0);
167: memcpy(stack_file[stack_idx],smb_file,128);
168: stack_sdt[stack_idx]=sdt_fp;
169: stack_shd[stack_idx]=shd_fp;
170: stack_sid[stack_idx]=sid_fp;
171: stack_sda[stack_idx]=sda_fp;
172: stack_sha[stack_idx]=sha_fp;
173: stack_idx++;
174: return(0); }
175: /* pop or xchng */
176: if(!stack_idx) /* Nothing on the stack, so do nothing */
177: return(0);
178: if(op==SMB_STACK_XCHNG) {
179: if(!shd_fp)
180: return(0);
181: memcpy(tmp_file,smb_file,128);
182: tmp_sdt=sdt_fp;
183: tmp_shd=shd_fp;
184: tmp_sid=sid_fp;
185: tmp_sda=sda_fp;
186: tmp_sha=sha_fp; }
187:
188: stack_idx--;
189: memcpy(smb_file,stack_file[stack_idx],128);
190: sdt_fp=stack_sdt[stack_idx];
191: shd_fp=stack_shd[stack_idx];
192: sid_fp=stack_sid[stack_idx];
193: sda_fp=stack_sda[stack_idx];
194: sha_fp=stack_sha[stack_idx];
195: if(op==SMB_STACK_XCHNG) {
196: stack_idx++;
197: memcpy(stack_file[stack_idx-1],tmp_file,128);
198: stack_sdt[stack_idx-1]=tmp_sdt;
199: stack_shd[stack_idx-1]=tmp_shd;
200: stack_sid[stack_idx-1]=tmp_sid;
201: stack_sda[stack_idx-1]=tmp_sda;
202: stack_sha[stack_idx-1]=tmp_sha; }
203: return(0);
204: }
205:
206: /****************************************************************************/
207: /* Truncates header file */
208: /* Retrys for retry_time number of seconds */
209: /* Return 0 on success, non-zero otherwise */
210: /****************************************************************************/
211: int smb_trunchdr(int retry_time)
212: {
213: long start;
214:
215: start=time(NULL);
216: rewind(shd_fp);
217: while(1) {
218: if(!chsize(fileno(shd_fp),0L))
219: break;
220: if(errno!=EACCES)
221: return(-1);
222: if(time(NULL)-start>=retry_time) /* Time-out */
223: return(-2); }
224: return(0);
225: }
226:
227: /*********************************/
228: /* Message Base Header Functions */
229: /*********************************/
230:
231: /****************************************************************************/
232: /* Attempts for retry_time number of seconds to lock the message base hdr */
233: /****************************************************************************/
234: int smb_locksmbhdr(int retry_time)
235: {
236: ulong start;
237:
238: start=time(NULL);
239: while(1) {
240: if(!lock(fileno(shd_fp),0L,sizeof(smbhdr_t)+sizeof(smbstatus_t)))
241: return(0);
242: if(time(NULL)-start>=retry_time)
243: break; /* Incase we've already locked it */
244: unlock(fileno(shd_fp),0L,sizeof(smbhdr_t)+sizeof(smbstatus_t)); }
245: return(-1);
246: }
247:
248: /****************************************************************************/
249: /* Read the SMB header from the header file and place into "status" */
250: /****************************************************************************/
251: int smb_getstatus(smbstatus_t *status)
252: {
253: char str[128];
254: int i;
255:
256: setvbuf(shd_fp,shd_buf,_IONBF,SHD_BLOCK_LEN);
257: clearerr(shd_fp);
258: fseek(shd_fp,sizeof(smbhdr_t),SEEK_SET);
259: i=fread(status,1,sizeof(smbstatus_t),shd_fp);
260: setvbuf(shd_fp,shd_buf,_IOFBF,SHD_BLOCK_LEN);
261: if(i==sizeof(smbstatus_t))
262: return(0);
263: return(1);
264: }
265:
266: /****************************************************************************/
267: /* Writes message base header */
268: /****************************************************************************/
269: int smb_putstatus(smbstatus_t status)
270: {
271: int i;
272:
273: clearerr(shd_fp);
274: fseek(shd_fp,sizeof(smbhdr_t),SEEK_SET);
275: i=fwrite(&status,1,sizeof(smbstatus_t),shd_fp);
276: fflush(shd_fp);
277: if(i==sizeof(smbstatus_t))
278: return(0);
279: return(1);
280: }
281:
282: /****************************************************************************/
283: /* Unlocks previously locks message base header */
284: /****************************************************************************/
285: int smb_unlocksmbhdr()
286: {
287: return(unlock(fileno(shd_fp),0L,sizeof(smbhdr_t)+sizeof(smbstatus_t)));
288: }
289:
290: /********************************/
291: /* Individual Message Functions */
292: /********************************/
293:
294: /****************************************************************************/
295: /* Attempts for retry_time number of seconds to lock the header for 'msg' */
296: /****************************************************************************/
297: int smb_lockmsghdr(smbmsg_t msg, int retry_time)
298: {
299: ulong start;
300:
301: start=time(NULL);
302: while(1) {
303: if(!lock(fileno(shd_fp),msg.idx.offset,sizeof(msghdr_t)))
304: return(0);
305: if(time(NULL)-start>=retry_time)
306: break;
307: unlock(fileno(shd_fp),msg.idx.offset,sizeof(msghdr_t)); }
308: return(-1);
309: }
310:
311: /****************************************************************************/
312: /* Fills msg->idx with message index based on msg->hdr.number */
313: /* OR if msg->hdr.number is 0, based on msg->offset (record offset). */
314: /* if msg.hdr.number does not equal 0, then msg->offset is filled too. */
315: /* Either msg->hdr.number or msg->offset must be initialized before */
316: /* calling this function */
317: /* Returns 1 if message number wasn't found, 0 if it was */
318: /****************************************************************************/
319: int smb_getmsgidx(smbmsg_t *msg)
320: {
321: idxrec_t idx;
322: ulong l,length,total,bot,top;
323:
324: clearerr(sid_fp);
325: if(!msg->hdr.number) {
326: fseek(sid_fp,msg->offset*sizeof(idxrec_t),SEEK_SET);
327: if(!fread(&msg->idx,sizeof(idxrec_t),1,sid_fp))
328: return(1);
329: return(0); }
330:
331: length=filelength(fileno(sid_fp));
332: if(!length)
333: return(1);
334: total=length/sizeof(idxrec_t);
335: if(!total)
336: return(1);
337:
338: bot=0;
339: top=total;
340: l=total/2; /* Start at middle index */
341: while(1) {
342: fseek(sid_fp,l*sizeof(idxrec_t),SEEK_SET);
343: if(!fread(&idx,sizeof(idxrec_t),1,sid_fp))
344: return(1);
345: if(bot==top-1 && idx.number!=msg->hdr.number)
346: return(1);
347: if(idx.number>msg->hdr.number) {
348: top=l;
349: l=bot+((top-bot)/2);
350: continue; }
351: if(idx.number<msg->hdr.number) {
352: bot=l;
353: l=top-((top-bot)/2);
354: continue; }
355: break; }
356: msg->idx=idx;
357: msg->offset=l;
358: return(0);
359: }
360:
361: /****************************************************************************/
362: /* Reads the last index record in the open message base */
363: /****************************************************************************/
364: int smb_getlastidx(idxrec_t *idx)
365: {
366: long length;
367:
368: clearerr(sid_fp);
369: length=filelength(fileno(sid_fp));
370: if(length<sizeof(idxrec_t))
371: return(-1);
372: fseek(sid_fp,length-sizeof(idxrec_t),SEEK_SET);
373: if(!fread(idx,sizeof(idxrec_t),1,sid_fp))
374: return(-2);
375: return(0);
376: }
377:
378: /****************************************************************************/
379: /* Figures out the total length of the header record for 'msg' */
380: /* Returns length */
381: /****************************************************************************/
382: uint smb_getmsghdrlen(smbmsg_t msg)
383: {
384: int i;
385:
386: /* fixed portion */
387: msg.hdr.length=sizeof(msghdr_t);
388: /* data fields */
389: msg.hdr.length+=msg.hdr.total_dfields*sizeof(dfield_t);
390: /* header fields */
391: for(i=0;i<msg.total_hfields;i++) {
392: msg.hdr.length+=sizeof(hfield_t);
393: msg.hdr.length+=msg.hfield[i].length; }
394: return(msg.hdr.length);
395: }
396:
397: /****************************************************************************/
398: /* Figures out the total length of the data buffer for 'msg' */
399: /* Returns length */
400: /****************************************************************************/
401: ulong smb_getmsgdatlen(smbmsg_t msg)
402: {
403: int i;
404: ulong length=0L;
405:
406: for(i=0;i<msg.hdr.total_dfields;i++)
407: length+=msg.dfield[i].length;
408: return(length);
409: }
410:
411: /****************************************************************************/
412: /* Read header information into 'msg' structure */
413: /* msg->idx.offset must be set before calling this function */
414: /* Must call smb_freemsgmem() to free memory allocated for var len strs */
415: /* Returns 0 on success, non-zero if error */
416: /****************************************************************************/
417: int smb_getmsghdr(smbmsg_t *msg)
418: {
419: ushort i;
420: ulong l,offset;
421: idxrec_t idx;
422:
423: rewind(shd_fp);
424: fseek(shd_fp,msg->idx.offset,SEEK_SET);
425: idx=msg->idx;
426: offset=msg->offset;
427: memset(msg,0,sizeof(smbmsg_t));
428: msg->idx=idx;
429: msg->offset=offset;
430: if(!fread(&msg->hdr,sizeof(msghdr_t),1,shd_fp))
431: return(-1);
432: if(memcmp(msg->hdr.id,"SHD\x1a",4))
433: return(-2);
434: if(msg->hdr.version<0x110)
435: return(-9);
436: l=sizeof(msghdr_t);
437: if(msg->hdr.total_dfields && (msg->dfield
438: =(dfield_t *)MALLOC(sizeof(dfield_t)*msg->hdr.total_dfields))==NULL) {
439: smb_freemsgmem(*msg);
440: return(-3); }
441: i=0;
442: while(i<msg->hdr.total_dfields && l<msg->hdr.length) {
443: if(!fread(&msg->dfield[i],sizeof(dfield_t),1,shd_fp)) {
444: smb_freemsgmem(*msg);
445: return(-4); }
446: i++;
447: l+=sizeof(dfield_t); }
448: if(i<msg->hdr.total_dfields) {
449: smb_freemsgmem(*msg);
450: return(-8); }
451:
452: while(l<msg->hdr.length) {
453: i=msg->total_hfields;
454: if((msg->hfield_dat=(void **)REALLOC(msg->hfield_dat,sizeof(void *)*(i+1)))
455: ==NULL) {
456: smb_freemsgmem(*msg);
457: return(-3); }
458: if((msg->hfield=(hfield_t *)REALLOC(msg->hfield
459: ,sizeof(hfield_t)*(i+1)))==NULL) {
460: smb_freemsgmem(*msg);
461: return(-3); }
462: msg->total_hfields++;
463: if(!fread(&msg->hfield[i],sizeof(hfield_t),1,shd_fp)) {
464: smb_freemsgmem(*msg);
465: return(-5); }
466: l+=sizeof(hfield_t);
467: if((msg->hfield_dat[i]=(char *)MALLOC(msg->hfield[i].length+1))
468: ==NULL) { /* Allocate 1 extra for NULL terminator */
469: smb_freemsgmem(*msg); /* or 0 length field */
470: return(-3); }
471: memset(msg->hfield_dat[i],0,msg->hfield[i].length+1); /* init to NULL */
472: if(msg->hfield[i].length
473: && !fread(msg->hfield_dat[i],msg->hfield[i].length,1,shd_fp)) {
474: smb_freemsgmem(*msg);
475: return(-6); }
476:
477: switch(msg->hfield[i].type) { /* convenience variables */
478: case SENDER:
479: if(!msg->from) {
480: msg->from=msg->hfield_dat[i];
481: break; }
482: case FORWARDED: /* fall through */
483: msg->forwarded=1;
484: break;
485: case SENDERAGENT:
486: if(!msg->forwarded)
487: msg->from_agent=*(ushort *)msg->hfield_dat[i];
488: break;
489: case SENDEREXT:
490: if(!msg->forwarded)
491: msg->from_ext=msg->hfield_dat[i];
492: break;
493: case SENDERNETTYPE:
494: if(!msg->forwarded)
495: msg->from_net.type=*(ushort *)msg->hfield_dat[i];
496: break;
497: case SENDERNETADDR:
498: if(!msg->forwarded)
499: msg->from_net.addr=msg->hfield_dat[i];
500: break;
501: case REPLYTO:
502: msg->replyto=msg->hfield_dat[i];
503: break;
504: case REPLYTOEXT:
505: msg->replyto_ext=msg->hfield_dat[i];
506: break;
507: case REPLYTOAGENT:
508: msg->replyto_agent=*(ushort *)msg->hfield_dat[i];
509: break;
510: case REPLYTONETTYPE:
511: msg->replyto_net.type=*(ushort *)msg->hfield_dat[i];
512: break;
513: case REPLYTONETADDR:
514: msg->replyto_net.addr=msg->hfield_dat[i];
515: break;
516: case RECIPIENT:
517: msg->to=msg->hfield_dat[i];
518: break;
519: case RECIPIENTEXT:
520: msg->to_ext=msg->hfield_dat[i];
521: break;
522: case RECIPIENTAGENT:
523: msg->to_agent=*(ushort *)msg->hfield_dat[i];
524: break;
525: case RECIPIENTNETTYPE:
526: msg->to_net.type=*(ushort *)msg->hfield_dat[i];
527: break;
528: case RECIPIENTNETADDR:
529: msg->to_net.addr=msg->hfield_dat[i];
530: break;
531: case SUBJECT:
532: msg->subj=msg->hfield_dat[i];
533: break; }
534: l+=msg->hfield[i].length; }
535:
536: if(!msg->from || !msg->to || !msg->subj) {
537: smb_freemsgmem(*msg);
538: return(-7); }
539: return(0);
540: }
541:
542: /****************************************************************************/
543: /* Frees memory allocated for 'msg' */
544: /****************************************************************************/
545: void smb_freemsgmem(smbmsg_t msg)
546: {
547: ushort i;
548:
549: if(msg.dfield)
550: FREE(msg.dfield);
551: for(i=0;i<msg.total_hfields;i++)
552: if(msg.hfield_dat[i])
553: FREE(msg.hfield_dat[i]);
554: if(msg.hfield)
555: FREE(msg.hfield);
556: if(msg.hfield_dat)
557: FREE(msg.hfield_dat);
558: }
559:
560: /****************************************************************************/
561: /* Unlocks header for 'msg' */
562: /****************************************************************************/
563: int smb_unlockmsghdr(smbmsg_t msg)
564: {
565: return(unlock(fileno(shd_fp),msg.idx.offset,sizeof(msghdr_t)));
566: }
567:
568:
569: /****************************************************************************/
570: /* Adds a header field to the 'msg' structure (in memory only) */
571: /****************************************************************************/
572: int smb_hfield(smbmsg_t *msg, ushort type, ushort length, void *data)
573: {
574: int i;
575:
576: i=msg->total_hfields;
577: if((msg->hfield=(hfield_t *)REALLOC(msg->hfield,sizeof(hfield_t)*(i+1)))
578: ==NULL)
579: return(1);
580: if((msg->hfield_dat=(void **)REALLOC(msg->hfield_dat,sizeof(void *)*(i+1)))
581: ==NULL)
582: return(2);
583: msg->total_hfields++;
584: msg->hfield[i].type=type;
585: msg->hfield[i].length=length;
586: if(length) {
587: if((msg->hfield_dat[i]=(void *)MALLOC(length))==NULL)
588: return(4);
589: memcpy(msg->hfield_dat[i],data,length); }
590: else
591: msg->hfield_dat[i]=NULL;
592: return(0);
593: }
594:
595: /****************************************************************************/
596: /* Adds a data field to the 'msg' structure (in memory only) */
597: /* Automatically figures out the offset into the data buffer from existing */
598: /* dfield lengths */
599: /****************************************************************************/
600: int smb_dfield(smbmsg_t *msg, ushort type, ulong length)
601: {
602: int i,j;
603:
604: i=msg->hdr.total_dfields;
605: if((msg->dfield=(dfield_t *)REALLOC(msg->dfield,sizeof(dfield_t)*(i+1)))
606: ==NULL)
607: return(1);
608: msg->hdr.total_dfields++;
609: msg->dfield[i].type=type;
610: msg->dfield[i].length=length;
611: for(j=msg->dfield[i].offset=0;j<i;j++)
612: msg->dfield[i].offset+=msg->dfield[j].length;
613: return(0);
614: }
615:
616: /****************************************************************************/
617: /* Checks CRC history file for duplicate crc. If found, returns 1. */
618: /* If no dupe, adds to CRC history and returns 0, or negative if error. */
619: /****************************************************************************/
620: int smb_addcrc(ulong max_crcs, ulong crc, int retry_time)
621: {
622: char str[128];
623: int file;
624: long length;
625: ulong l,*buf;
626: time_t start;
627:
628: if(!max_crcs)
629: return(0);
630: start=time(NULL);
631: sprintf(str,"%s.SCH",smb_file);
632: while(1) {
633: if((file=sopen(str,O_RDWR|O_CREAT|O_BINARY,SH_DENYRW,S_IWRITE|S_IREAD))!=-1)
634: break;
635: if(errno!=EACCES)
636: return(-1);
637: if(time(NULL)-start>=retry_time)
638: return(-2); }
639: length=filelength(file);
640: if(length<0L) {
641: close(file);
642: return(-4); }
643: if((buf=(ulong *)MALLOC(max_crcs*4))==NULL) {
644: close(file);
645: return(-3); }
646: if(length>=max_crcs*4) { /* Reached or exceeds max crcs */
647: read(file,buf,max_crcs*4);
648: for(l=0;l<max_crcs;l++)
649: if(crc==buf[l])
650: break;
651: if(l<max_crcs) { /* Dupe CRC found */
652: close(file);
653: FREE(buf);
654: return(1); }
655: chsize(file,0L); /* truncate it */
656: lseek(file,0L,SEEK_SET);
657: write(file,buf+4,(max_crcs-1)*4); }
658:
659: else if(length/4) { /* Less than max crcs */
660: read(file,buf,length);
661: for(l=0;l<length/4;l++)
662: if(crc==buf[l])
663: break;
664: if(l<length/4) { /* Dupe CRC found */
665: close(file);
666: FREE(buf);
667: return(1); } }
668:
669: lseek(file,0L,SEEK_END);
670: write(file,&crc,4); /* Write to the end */
671: FREE(buf);
672: close(file);
673: return(0);
674: }
675:
676:
677: /****************************************************************************/
678: /* Creates a new message header record in the header file. */
679: /* If storage is SMB_SELFPACK, self-packing conservative allocation is used */
680: /* If storage is SMB_FASTALLOC, fast allocation is used */
681: /* If storage is SMB_HYPERALLOC, no allocation tables are used (fastest) */
682: /****************************************************************************/
683: int smb_addmsghdr(smbmsg_t *msg, smbstatus_t *status, int storage
684: ,int retry_time)
685: {
686: int i;
687: long l;
688:
689: if(smb_locksmbhdr(retry_time))
690: return(1);
691: if(smb_getstatus(status))
692: return(2);
693:
694: if(storage!=SMB_HYPERALLOC && (i=smb_open_ha(retry_time))!=0)
695: return(i);
696:
697: msg->hdr.length=smb_getmsghdrlen(*msg);
698: if(storage==SMB_HYPERALLOC)
699: l=smb_hallochdr(status->header_offset);
700: else if(storage==SMB_FASTALLOC)
701: l=smb_fallochdr(msg->hdr.length);
702: else
703: l=smb_allochdr(msg->hdr.length);
704: if(l==-1L) {
705: smb_unlocksmbhdr();
706: fclose(sha_fp);
707: return(-1); }
708:
709: status->last_msg++;
710: msg->idx.number=msg->hdr.number=status->last_msg;
711: msg->idx.offset=status->header_offset+l;
712: msg->idx.time=msg->hdr.when_imported.time;
713: msg->idx.attr=msg->hdr.attr;
714: msg->offset=status->total_msgs;
715: status->total_msgs++;
716: smb_putstatus(*status);
717:
718: if(storage!=SMB_HYPERALLOC)
719: fclose(sha_fp);
720: i=smb_putmsg(*msg);
721: smb_unlocksmbhdr();
722: return(i);
723: }
724:
725: /****************************************************************************/
726: /* Writes both header and index information for msg 'msg' */
727: /****************************************************************************/
728: int smb_putmsg(smbmsg_t msg)
729: {
730: int i;
731:
732: i=smb_putmsghdr(msg);
733: if(i)
734: return(i);
735: return(smb_putmsgidx(msg));
736: }
737:
738: /****************************************************************************/
739: /* Writes index information for 'msg' */
740: /* msg.idx */
741: /* and msg.offset must be set prior to calling to this function */
742: /* Returns 0 if everything ok */
743: /****************************************************************************/
744: int smb_putmsgidx(smbmsg_t msg)
745: {
746:
747: clearerr(sid_fp);
748: fseek(sid_fp,msg.offset*sizeof(idxrec_t),SEEK_SET);
749: if(!fwrite(&msg.idx,sizeof(idxrec_t),1,sid_fp))
750: return(1);
751: fflush(sid_fp);
752: return(0);
753: }
754:
755: /****************************************************************************/
756: /* Writes header information for 'msg' */
757: /* msg.hdr.length */
758: /* msg.idx.offset */
759: /* and msg.offset must be set prior to calling to this function */
760: /* Returns 0 if everything ok */
761: /****************************************************************************/
762: int smb_putmsghdr(smbmsg_t msg)
763: {
764: ushort i;
765: ulong l;
766:
767: clearerr(shd_fp);
768: if(fseek(shd_fp,msg.idx.offset,SEEK_SET))
769: return(-1);
770:
771: /************************************************/
772: /* Write the fixed portion of the header record */
773: /************************************************/
774: if(!fwrite(&msg.hdr,sizeof(msghdr_t),1,shd_fp))
775: return(-2);
776:
777: /************************************************/
778: /* Write the data fields (each is fixed length) */
779: /************************************************/
780: for(i=0;i<msg.hdr.total_dfields;i++)
781: if(!fwrite(&msg.dfield[i],sizeof(dfield_t),1,shd_fp))
782: return(-3);
783:
784: /*******************************************/
785: /* Write the variable length header fields */
786: /*******************************************/
787: for(i=0;i<msg.total_hfields;i++) {
788: if(!fwrite(&msg.hfield[i],sizeof(hfield_t),1,shd_fp))
789: return(-4);
790: if(msg.hfield[i].length /* more then 0 bytes long */
791: && !fwrite(msg.hfield_dat[i],msg.hfield[i].length,1,shd_fp))
792: return(-5); }
793:
794: l=smb_getmsghdrlen(msg);
795: while(l%SHD_BLOCK_LEN) {
796: if(fputc(0,shd_fp)==EOF)
797: return(-6); /* pad block with NULL */
798: l++; }
799: fflush(shd_fp);
800: return(0);
801: }
802:
803: /****************************************************************************/
804: /* Creates a sub-board's initial header file */
805: /* Truncates and deletes other associated SMB files */
806: /****************************************************************************/
807: int smb_create(ulong max_crcs, ulong max_msgs, ushort max_age, ushort attr
808: ,int retry_time)
809: {
810: char str[128];
811: smbhdr_t hdr;
812: smbstatus_t status;
813:
814: if(filelength(fileno(shd_fp))>=sizeof(smbhdr_t)+sizeof(smbstatus_t)
815: && smb_locksmbhdr(retry_time)) /* header exists, so lock it */
816: return(1);
817: memset(&hdr,0,sizeof(smbhdr_t));
818: memset(&status,0,sizeof(smbstatus_t));
819: memcpy(hdr.id,"SMB\x1a",4); /* <S> <M> <B> <^Z> */
820: hdr.version=SMB_VERSION;
821: hdr.length=sizeof(smbhdr_t)+sizeof(smbstatus_t);
822: status.last_msg=status.total_msgs=0;
823: status.header_offset=sizeof(smbhdr_t)+sizeof(smbstatus_t);
824: status.max_crcs=max_crcs;
825: status.max_msgs=max_msgs;
826: status.max_age=max_age;
827: status.attr=attr;
828: rewind(shd_fp);
829: fwrite(&hdr,1,sizeof(smbhdr_t),shd_fp);
830: fwrite(&status,1,sizeof(smbstatus_t),shd_fp);
831: rewind(shd_fp);
832: chsize(fileno(shd_fp),sizeof(smbhdr_t)+sizeof(smbstatus_t));
833: fflush(shd_fp);
834:
835: rewind(sdt_fp);
836: chsize(fileno(sdt_fp),0L);
837: rewind(sid_fp);
838: chsize(fileno(sid_fp),0L);
839:
840: sprintf(str,"%s.SDA",smb_file);
841: remove(str); /* if it exists, delete it */
842: sprintf(str,"%s.SHA",smb_file);
843: remove(str); /* if it exists, delete it */
844: sprintf(str,"%s.SCH",smb_file);
845: remove(str);
846: smb_unlocksmbhdr();
847: return(0);
848: }
849:
850: /****************************************************************************/
851: /* Returns number of data blocks required to store "length" amount of data */
852: /****************************************************************************/
853: ulong smb_datblocks(ulong length)
854: {
855: ulong blocks;
856:
857: blocks=length/SDT_BLOCK_LEN;
858: if(length%SDT_BLOCK_LEN)
859: blocks++;
860: return(blocks);
861: }
862:
863: /****************************************************************************/
864: /* Returns number of header blocks required to store "length" size header */
865: /****************************************************************************/
866: ulong smb_hdrblocks(ulong length)
867: {
868: ulong blocks;
869:
870: blocks=length/SHD_BLOCK_LEN;
871: if(length%SHD_BLOCK_LEN)
872: blocks++;
873: return(blocks);
874: }
875:
876: /****************************************************************************/
877: /* Finds unused space in data file based on block allocation table and */
878: /* marks space as used in allocation table. */
879: /* File must be opened read/write DENY ALL */
880: /* Returns offset to beginning of data (in bytes, not blocks) */
881: /* Assumes smb_open_da() has been called */
882: /* fclose(sda_fp) should be called after */
883: /* Returns negative on error */
884: /****************************************************************************/
885: long smb_allocdat(ulong length, ushort headers)
886: {
887: ushort i,j;
888: ulong l,blocks,offset=0L;
889:
890: blocks=smb_datblocks(length);
891: j=0; /* j is consecutive unused block counter */
892: fflush(sda_fp);
893: rewind(sda_fp);
894: while(!feof(sda_fp)) {
895: if(!fread(&i,2,1,sda_fp))
896: break;
897: offset+=SDT_BLOCK_LEN;
898: if(!i) j++;
899: else j=0;
900: if(j==blocks) {
901: offset-=(blocks*SDT_BLOCK_LEN);
902: break; } }
903: clearerr(sda_fp);
904: fseek(sda_fp,(offset/SDT_BLOCK_LEN)*2L,SEEK_SET);
905: for(l=0;l<blocks;l++)
906: if(!fwrite(&headers,2,1,sda_fp))
907: return(-1);
908: fflush(sda_fp);
909: return(offset);
910: }
911:
912: /****************************************************************************/
913: /* Allocates space for data, but doesn't search for unused blocks */
914: /* Returns negative on error */
915: /****************************************************************************/
916: long smb_fallocdat(ulong length, ushort headers)
917: {
918: ulong l,blocks,offset;
919:
920: fflush(sda_fp);
921: clearerr(sda_fp);
922: blocks=smb_datblocks(length);
923: fseek(sda_fp,0L,SEEK_END);
924: offset=(ftell(sda_fp)/2L)*SDT_BLOCK_LEN;
925: for(l=0;l<blocks;l++)
926: if(!fwrite(&headers,2,1,sda_fp))
927: break;
928: fflush(sda_fp);
929: if(l<blocks)
930: return(-1L);
931: return(offset);
932: }
933:
934: /****************************************************************************/
935: /* De-allocates space for data */
936: /* Returns non-zero on error */
937: /****************************************************************************/
938: int smb_freemsgdat(ulong offset, ulong length, ushort headers)
939: {
940: ushort i;
941: ulong l,blocks;
942:
943: blocks=smb_datblocks(length);
944:
945: clearerr(sda_fp);
946: for(l=0;l<blocks;l++) {
947: if(fseek(sda_fp,((offset/SDT_BLOCK_LEN)+l)*2L,SEEK_SET))
948: return(1);
949: if(!fread(&i,2,1,sda_fp))
950: return(2);
951: if(headers>i)
952: i=0; /* don't want to go negative */
953: else
954: i-=headers;
955: if(fseek(sda_fp,-2L,SEEK_CUR))
956: return(3);
957: if(!fwrite(&i,2,1,sda_fp))
958: return(4); }
959: fflush(sda_fp);
960: return(0);
961: }
962:
963: /****************************************************************************/
964: /* Adds to data allocation records for blocks starting at 'offset' */
965: /* Returns non-zero on error */
966: /****************************************************************************/
967: int smb_incdat(ulong offset, ulong length, ushort headers)
968: {
969: ushort i;
970: ulong l,blocks;
971:
972: clearerr(sda_fp);
973: blocks=smb_datblocks(length);
974: for(l=0;l<blocks;l++) {
975: fseek(sda_fp,((offset/SDT_BLOCK_LEN)+l)*2L,SEEK_SET);
976: if(!fread(&i,2,1,sda_fp))
977: return(1);
978: i+=headers;
979: fseek(sda_fp,-2L,SEEK_CUR);
980: if(!fwrite(&i,2,1,sda_fp))
981: return(2); }
982: fflush(sda_fp);
983: return(0);
984: }
985:
986: /****************************************************************************/
987: /* De-allocates blocks for header record */
988: /* Returns non-zero on error */
989: /****************************************************************************/
990: int smb_freemsghdr(ulong offset, ulong length)
991: {
992: uchar c=0;
993: ulong l,blocks;
994:
995: clearerr(sha_fp);
996: blocks=smb_hdrblocks(length);
997: fseek(sha_fp,offset/SHD_BLOCK_LEN,SEEK_SET);
998: for(l=0;l<blocks;l++)
999: if(!fwrite(&c,1,1,sha_fp))
1000: return(1);
1001: fflush(sha_fp);
1002: return(0);
1003: }
1004:
1005: /****************************************************************************/
1006: /* Frees all allocated header and data blocks for 'msg' */
1007: /****************************************************************************/
1008: int smb_freemsg(smbmsg_t msg, smbstatus_t status)
1009: {
1010: int i;
1011: ushort x;
1012:
1013: if(status.attr&SMB_HYPERALLOC) /* Nothing to do */
1014: return(0);
1015:
1016: for(x=0;x<msg.hdr.total_dfields;x++) {
1017: if((i=smb_freemsgdat(msg.hdr.offset+msg.dfield[x].offset
1018: ,msg.dfield[x].length,1))!=0)
1019: return(i); }
1020: return(smb_freemsghdr(msg.idx.offset-status.header_offset,msg.hdr.length));
1021: }
1022:
1023: /****************************************************************************/
1024: /* Finds unused space in header file based on block allocation table and */
1025: /* marks space as used in allocation table. */
1026: /* File must be opened read/write DENY ALL */
1027: /* Returns offset to beginning of header (in bytes, not blocks) */
1028: /* Assumes smb_open_ha() has been called */
1029: /* fclose(sha_fp) should be called after */
1030: /* Returns -1L on error */
1031: /****************************************************************************/
1032: long smb_allochdr(ulong length)
1033: {
1034: uchar c;
1035: ushort i;
1036: ulong l,blocks,offset=0;
1037:
1038: blocks=smb_hdrblocks(length);
1039: i=0; /* i is consecutive unused block counter */
1040: fflush(sha_fp);
1041: rewind(sha_fp);
1042: while(!feof(sha_fp)) {
1043: if(!fread(&c,1,1,sha_fp))
1044: break;
1045: offset+=SHD_BLOCK_LEN;
1046: if(!c) i++;
1047: else i=0;
1048: if(i==blocks) {
1049: offset-=(blocks*SHD_BLOCK_LEN);
1050: break; } }
1051: clearerr(sha_fp);
1052: fseek(sha_fp,offset/SHD_BLOCK_LEN,SEEK_SET);
1053: c=1;
1054: for(l=0;l<blocks;l++)
1055: if(!fwrite(&c,1,1,sha_fp))
1056: return(-1L);
1057: fflush(sha_fp);
1058: return(offset);
1059: }
1060:
1061: /****************************************************************************/
1062: /* Allocates space for index, but doesn't search for unused blocks */
1063: /* Returns -1L on error */
1064: /****************************************************************************/
1065: long smb_fallochdr(ulong length)
1066: {
1067: uchar c=1;
1068: ulong l,blocks,offset;
1069:
1070: blocks=smb_hdrblocks(length);
1071: fflush(sha_fp);
1072: clearerr(sha_fp);
1073: fseek(sha_fp,0L,SEEK_END);
1074: offset=ftell(sha_fp)*SHD_BLOCK_LEN;
1075: for(l=0;l<blocks;l++)
1076: if(!fwrite(&c,1,1,sha_fp))
1077: return(-1L);
1078: fflush(sha_fp);
1079: return(offset);
1080: }
1081:
1082: /************************************************************************/
1083: /* Allocate header blocks using Hyper Allocation */
1084: /* this function should be most likely not be called from anywhere but */
1085: /* smb_addmsghdr() */
1086: /************************************************************************/
1087: long smb_hallochdr(ulong header_offset)
1088: {
1089: long l;
1090:
1091: fflush(shd_fp);
1092: fseek(shd_fp,0L,SEEK_END);
1093: l=ftell(shd_fp);
1094: if(l<header_offset) /* Header file truncated?!? */
1095: return(header_offset);
1096: while((l-header_offset)%SHD_BLOCK_LEN) /* Make sure even block boundry */
1097: l++;
1098: return(l-header_offset);
1099: }
1100:
1101: /************************************************************************/
1102: /* Allocate data blocks using Hyper Allocation */
1103: /* smb_locksmbhdr() should be called before this function and not */
1104: /* unlocked until all data fields for this message have been written */
1105: /* to the SDT file */
1106: /************************************************************************/
1107: long smb_hallocdat()
1108: {
1109: long l;
1110:
1111: fflush(sdt_fp);
1112: fseek(sdt_fp,0L,SEEK_END);
1113: l=ftell(sdt_fp);
1114: if(l<=0)
1115: return(l);
1116: while(l%SDT_BLOCK_LEN) /* Make sure even block boundry */
1117: l++;
1118: return(l);
1119: }
1120:
1121: /* End of SMBLIB.C */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.