|
|
1.1 root 1: /* smblib.c */
2:
3: /* Synchronet message base (SMB) library routines */
4:
1.1.1.2 ! root 5: /* $Id: smblib.c,v 1.147 2011/07/21 19:05:18 rswindell 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: * *
1.1.1.2 ! root 11: * Copyright 2011 Rob Swindell - http://www.synchro.net/copyright.html *
1.1 root 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: /* ANSI C Library headers */
39:
40: #include <time.h>
41: #include <errno.h>
42: #include <fcntl.h>
43: #include <stdio.h>
44: #include <stdlib.h> /* malloc */
45: #include <string.h>
46: #include <ctype.h> /* isdigit */
47: #include <sys/types.h>
48: #include <sys/stat.h> /* must come after sys/types.h */
49:
50: /* SMB-specific headers */
51: #include "smblib.h"
52: #include "genwrap.h"
53: #include "filewrap.h"
54:
55: /* Use smb_ver() and smb_lib_ver() to obtain these values */
1.1.1.2 ! root 56: #define SMBLIB_VERSION "2.51" /* SMB library version */
1.1 root 57: #define SMB_VERSION 0x0121 /* SMB format version */
58: /* High byte major, low byte minor */
59:
60: static char* nulstr="";
61:
62: int SMBCALL smb_ver(void)
63: {
64: return(SMB_VERSION);
65: }
66:
67: char* SMBCALL smb_lib_ver(void)
68: {
69: return(SMBLIB_VERSION);
70: }
71:
72: /****************************************************************************/
73: /* Open a message base of name 'smb->file' */
74: /* Opens files for READing messages or updating message indices only */
75: /****************************************************************************/
76: int SMBCALL smb_open(smb_t* smb)
77: {
78: int i;
79: time_t start=0;
80: smbhdr_t hdr;
81:
82: /* Set default values, if uninitialized */
83: if(!smb->retry_time)
84: smb->retry_time=10; /* seconds */
85: if(!smb->retry_delay
86: || smb->retry_delay>(smb->retry_time*100)) /* at least ten retries */
87: smb->retry_delay=250; /* milliseconds */
88: smb->shd_fp=smb->sdt_fp=smb->sid_fp=NULL;
89: smb->sha_fp=smb->sda_fp=smb->hash_fp=NULL;
90: smb->last_error[0]=0;
91:
92: /* Check for message-base lock semaphore file (under maintenance?) */
93: while(smb_islocked(smb)) {
94: if(!start)
95: start=time(NULL);
96: else
97: if(time(NULL)-start>=(time_t)smb->retry_time)
98: return(SMB_ERR_TIMEOUT);
99: SLEEP(smb->retry_delay);
100: }
101:
102: if((i=smb_open_fp(smb,&smb->shd_fp,SH_DENYNO))!=SMB_SUCCESS)
103: return(i);
104:
105: memset(&(smb->status),0,sizeof(smb->status));
106: if(filelength(fileno(smb->shd_fp))>=(long)sizeof(smbhdr_t)) {
107: if(smb_locksmbhdr(smb)!=SMB_SUCCESS) {
108: smb_close(smb);
109: /* smb_lockmsghdr set last_error */
110: return(SMB_ERR_LOCK);
111: }
112: memset(&hdr,0,sizeof(smbhdr_t));
113: if(smb_fread(smb,&hdr,sizeof(smbhdr_t),smb->shd_fp)!=sizeof(smbhdr_t)) {
114: safe_snprintf(smb->last_error,sizeof(smb->last_error)
115: ,"%d '%s' reading header"
116: ,get_errno(),STRERROR(get_errno()));
117: smb_close(smb);
118: return(SMB_ERR_READ);
119: }
120: if(memcmp(hdr.id,SMB_HEADER_ID,LEN_HEADER_ID)) {
121: safe_snprintf(smb->last_error,sizeof(smb->last_error)
122: ,"corrupt SMB header ID: %.*s"
123: ,LEN_HEADER_ID,hdr.id);
124: smb_close(smb);
125: return(SMB_ERR_HDR_ID);
126: }
127: if(hdr.version<0x110) { /* Compatibility check */
128: safe_snprintf(smb->last_error,sizeof(smb->last_error)
129: ,"insufficient header version: %X"
130: ,hdr.version);
131: smb_close(smb);
132: return(SMB_ERR_HDR_VER);
133: }
134: if(smb_fread(smb,&(smb->status),sizeof(smbstatus_t),smb->shd_fp)!=sizeof(smbstatus_t)) {
135: safe_snprintf(smb->last_error,sizeof(smb->last_error)
136: ,"%d '%s' reading status"
137: ,get_errno(),STRERROR(get_errno()));
138: smb_close(smb);
139: return(SMB_ERR_READ);
140: }
141: if((i=smb_unlocksmbhdr(smb))!=SMB_SUCCESS) {
142: smb_close(smb);
143: return(i);
144: }
145: rewind(smb->shd_fp);
146: }
147:
148: if((i=smb_open_fp(smb,&smb->sdt_fp,SH_DENYNO))!=SMB_SUCCESS)
149: return(i);
150:
151: if((i=smb_open_fp(smb,&smb->sid_fp,SH_DENYNO))!=SMB_SUCCESS)
152: return(i);
153:
154: return(SMB_SUCCESS);
155: }
156:
157: /****************************************************************************/
158: /* Closes the currently open message base */
159: /****************************************************************************/
160: void SMBCALL smb_close(smb_t* smb)
161: {
162: if(smb->shd_fp!=NULL) {
163: smb_unlocksmbhdr(smb); /* In case it's been locked */
164: smb_close_fp(&smb->shd_fp);
165: }
166: smb_close_fp(&smb->sdt_fp);
167: smb_close_fp(&smb->sid_fp);
168: smb_close_fp(&smb->sda_fp);
169: smb_close_fp(&smb->sha_fp);
170: smb_close_fp(&smb->hash_fp);
171: }
172:
173: /****************************************************************************/
174: /* This set of functions is used to exclusively-lock an entire message base */
175: /* against any other process opening any of the message base files. */
176: /* Currently, this is only used while smbutil packs a message base. */
177: /* This is achieved with a semaphore lock file (e.g. mail.lock). */
178: /****************************************************************************/
179: static char* smb_lockfname(smb_t* smb, char* fname, size_t maxlen)
180: {
181: safe_snprintf(fname,maxlen,"%s.lock",smb->file);
182: return(fname);
183: }
184:
185: /****************************************************************************/
186: /* This function is used to lock an entire message base for exclusive */
187: /* (typically for maintenance/repair) */
188: /****************************************************************************/
189: int SMBCALL smb_lock(smb_t* smb)
190: {
191: char path[MAX_PATH+1];
192: int file;
193: time_t start=0;
194:
195: smb_lockfname(smb,path,sizeof(path)-1);
196: while((file=open(path,O_CREAT|O_EXCL|O_RDWR,S_IREAD|S_IWRITE))==-1) {
197: if(!start)
198: start=time(NULL);
199: else
200: if(time(NULL)-start>=(time_t)smb->retry_time) {
201: safe_snprintf(smb->last_error,sizeof(smb->last_error)
202: ,"%d '%s' creating %s"
203: ,get_errno(),STRERROR(get_errno()),path);
204: return(SMB_ERR_LOCK);
205: }
206: SLEEP(smb->retry_delay);
207: }
208: close(file);
209: return(SMB_SUCCESS);
210: }
211:
212: int SMBCALL smb_unlock(smb_t* smb)
213: {
214: char path[MAX_PATH+1];
215:
216: smb_lockfname(smb,path,sizeof(path)-1);
217: if(remove(path)!=0) {
218: safe_snprintf(smb->last_error,sizeof(smb->last_error)
219: ,"%d '%s' removing %s"
220: ,get_errno(),STRERROR(get_errno()),path);
221: return(SMB_ERR_DELETE);
222: }
223: return(SMB_SUCCESS);
224: }
225:
226: BOOL SMBCALL smb_islocked(smb_t* smb)
227: {
228: char path[MAX_PATH+1];
229:
230: if(access(smb_lockfname(smb,path,sizeof(path)-1),0)!=0)
231: return(FALSE);
232: safe_snprintf(smb->last_error,sizeof(smb->last_error),"%s exists",path);
233: return(TRUE);
234: }
235:
236: /****************************************************************************/
237: /* If the parameter 'push' is non-zero, this function stores the currently */
238: /* open message base to the "virtual" smb stack. Up to SMB_STACK_LEN */
239: /* message bases may be stored (defined in SMBDEFS.H). */
240: /* The parameter 'op' is the operation to perform on the stack. Either */
241: /* SMB_STACK_PUSH, SMB_STACK_POP, or SMB_STACK_XCHNG */
242: /* If the operation is SMB_STACK_POP, this function restores a message base */
243: /* previously saved with a SMB_STACK_PUSH call to this same function. */
244: /* If the operation is SMB_STACK_XCHNG, then the current message base is */
245: /* exchanged with the message base on the top of the stack (most recently */
246: /* pushed. */
247: /* If the current message base is not open, the SMB_STACK_PUSH and */
248: /* SMB_STACK_XCHNG operations do nothing */
249: /* Returns 0 on success, non-zero if stack full. */
250: /* If operation is SMB_STACK_POP or SMB_STACK_XCHNG, it always returns 0. */
251: /****************************************************************************/
252: int SMBCALL smb_stack(smb_t* smb, int op)
253: {
254: static smb_t stack[SMB_STACK_LEN];
255: static int stack_idx;
256: smb_t tmp_smb;
257:
258: if(op==SMB_STACK_PUSH) {
259: if(stack_idx>=SMB_STACK_LEN) {
260: safe_snprintf(smb->last_error,sizeof(smb->last_error),"SMB stack overflow");
261: return(SMB_FAILURE);
262: }
263: if(smb->shd_fp==NULL || smb->sdt_fp==NULL || smb->sid_fp==NULL)
264: return(SMB_SUCCESS); /* Msg base not open, do nothing */
265: memcpy(&stack[stack_idx],smb,sizeof(smb_t));
266: stack_idx++;
267: return(SMB_SUCCESS);
268: }
269: /* pop or xchng */
270: if(!stack_idx) /* Nothing on the stack, so do nothing */
271: return(SMB_SUCCESS);
272: if(op==SMB_STACK_XCHNG) {
273: if(smb->shd_fp==NULL)
274: return(SMB_SUCCESS);
275: memcpy(&tmp_smb,smb,sizeof(smb_t));
276: }
277:
278: stack_idx--;
279: memcpy(smb,&stack[stack_idx],sizeof(smb_t));
280: if(op==SMB_STACK_XCHNG) {
281: memcpy(&stack[stack_idx],&tmp_smb,sizeof(smb_t));
282: stack_idx++;
283: }
284: return(SMB_SUCCESS);
285: }
286:
287: /****************************************************************************/
288: /* Truncates header file */
289: /* Retrys for smb.retry_time number of seconds */
290: /* Return 0 on success, non-zero otherwise */
291: /****************************************************************************/
292: int SMBCALL smb_trunchdr(smb_t* smb)
293: {
294: time_t start=0;
295:
296: if(smb->shd_fp==NULL) {
297: safe_snprintf(smb->last_error,sizeof(smb->last_error),"msgbase not open");
298: return(SMB_ERR_NOT_OPEN);
299: }
300: rewind(smb->shd_fp);
301: while(1) {
302: if(chsize(fileno(smb->shd_fp),0L)==0)
303: break;
304: if(get_errno()!=EACCES && get_errno()!=EAGAIN) {
305: safe_snprintf(smb->last_error,sizeof(smb->last_error)
306: ,"%d '%s' changing header file size"
307: ,get_errno(),STRERROR(get_errno()));
308: return(SMB_ERR_WRITE);
309: }
310: if(!start)
311: start=time(NULL);
312: else
313: if(time(NULL)-start>=(time_t)smb->retry_time) { /* Time-out */
314: safe_snprintf(smb->last_error,sizeof(smb->last_error)
315: ,"timeout changing header file size (retry_time=%ld)"
316: ,smb->retry_time);
317: return(SMB_ERR_TIMEOUT);
318: }
319: SLEEP(smb->retry_delay);
320: }
321: return(SMB_SUCCESS);
322: }
323:
324: /*********************************/
325: /* Message Base Header Functions */
326: /*********************************/
327:
328: /****************************************************************************/
329: /* Attempts for smb.retry_time number of seconds to lock the msg base hdr */
330: /****************************************************************************/
331: int SMBCALL smb_locksmbhdr(smb_t* smb)
332: {
333: time_t start=0;
334:
335: if(smb->shd_fp==NULL) {
336: safe_snprintf(smb->last_error,sizeof(smb->last_error),"msgbase not open");
337: return(SMB_ERR_NOT_OPEN);
338: }
339: while(1) {
340: if(lock(fileno(smb->shd_fp),0L,sizeof(smbhdr_t)+sizeof(smbstatus_t))==0) {
341: smb->locked=TRUE;
342: return(SMB_SUCCESS);
343: }
344: if(!start)
345: start=time(NULL);
346: else
347: if(time(NULL)-start>=(time_t)smb->retry_time)
348: break;
349: /* In case we've already locked it */
350: if(unlock(fileno(smb->shd_fp),0L,sizeof(smbhdr_t)+sizeof(smbstatus_t))==0)
351: smb->locked=FALSE;
352: else {
353: SLEEP(smb->retry_delay);
354: }
355: }
356: safe_snprintf(smb->last_error,sizeof(smb->last_error),"timeout locking message base");
357: return(SMB_ERR_TIMEOUT);
358: }
359:
360: /****************************************************************************/
361: /* Read the SMB header from the header file and place into smb.status */
362: /****************************************************************************/
363: int SMBCALL smb_getstatus(smb_t* smb)
364: {
365: int i;
366:
367: if(smb->shd_fp==NULL) {
368: safe_snprintf(smb->last_error,sizeof(smb->last_error),"msgbase not open");
369: return(SMB_ERR_NOT_OPEN);
370: }
371: clearerr(smb->shd_fp);
372: if(fseek(smb->shd_fp,sizeof(smbhdr_t),SEEK_SET)) {
373: safe_snprintf(smb->last_error,sizeof(smb->last_error)
374: ,"%d '%s' seeking to %u in header file"
375: ,get_errno(),STRERROR(get_errno()),sizeof(smbhdr_t));
376: return(SMB_ERR_SEEK);
377: }
378: i=smb_fread(smb,&(smb->status),sizeof(smbstatus_t),smb->shd_fp);
379: if(i==sizeof(smbstatus_t))
380: return(SMB_SUCCESS);
381: safe_snprintf(smb->last_error,sizeof(smb->last_error)
382: ,"%d '%s' reading status",get_errno(),STRERROR(get_errno()));
383: return(SMB_ERR_READ);
384: }
385:
386: /****************************************************************************/
387: /* Writes message base header */
388: /****************************************************************************/
389: int SMBCALL smb_putstatus(smb_t* smb)
390: {
391: int i;
392:
393: if(smb->shd_fp==NULL) {
394: safe_snprintf(smb->last_error,sizeof(smb->last_error),"msgbase not open");
395: return(SMB_ERR_NOT_OPEN);
396: }
397: clearerr(smb->shd_fp);
398: if(fseek(smb->shd_fp,sizeof(smbhdr_t),SEEK_SET)) {
399: safe_snprintf(smb->last_error,sizeof(smb->last_error)
400: ,"%d '%s' seeking to %u in header file"
401: ,get_errno(),STRERROR(get_errno()),sizeof(smbhdr_t));
402: return(SMB_ERR_SEEK);
403: }
404: i=fwrite(&(smb->status),1,sizeof(smbstatus_t),smb->shd_fp);
405: fflush(smb->shd_fp);
406: if(i==sizeof(smbstatus_t))
407: return(SMB_SUCCESS);
408: safe_snprintf(smb->last_error,sizeof(smb->last_error)
409: ,"%d '%s' writing status",get_errno(),STRERROR(get_errno()));
410: return(SMB_ERR_WRITE);
411: }
412:
413: /****************************************************************************/
414: /* Unlocks previously locked message base header */
415: /****************************************************************************/
416: int SMBCALL smb_unlocksmbhdr(smb_t* smb)
417: {
418: if(smb->locked) {
419: if(smb->shd_fp==NULL) {
420: safe_snprintf(smb->last_error,sizeof(smb->last_error),"msgbase not open");
421: return(SMB_ERR_NOT_OPEN);
422: }
423: if(unlock(fileno(smb->shd_fp),0L,sizeof(smbhdr_t)+sizeof(smbstatus_t))!=0) {
424: safe_snprintf(smb->last_error,sizeof(smb->last_error)
425: ,"%d '%s' unlocking message base header",get_errno(),STRERROR(get_errno()));
426: return(SMB_ERR_UNLOCK);
427: }
428: smb->locked=FALSE;
429: }
430: return(SMB_SUCCESS);
431: }
432:
433: /********************************/
434: /* Individual Message Functions */
435: /********************************/
436:
437: /****************************************************************************/
438: /* Is the offset a valid message header offset? */
439: /****************************************************************************/
440: BOOL SMBCALL smb_valid_hdr_offset(smb_t* smb, ulong offset)
441: {
442: if(offset<sizeof(smbhdr_t)+sizeof(smbstatus_t)
443: || offset<smb->status.header_offset) {
444: safe_snprintf(smb->last_error,sizeof(smb->last_error)
445: ,"invalid header offset: %lu (0x%lX)"
446: ,offset,offset);
447: return(FALSE);
448: }
449: return(TRUE);
450: }
451:
452: /****************************************************************************/
453: /* Attempts for smb.retry_time number of seconds to lock the hdr for 'msg' */
454: /****************************************************************************/
455: int SMBCALL smb_lockmsghdr(smb_t* smb, smbmsg_t* msg)
456: {
457: time_t start=0;
458:
459: if(smb->shd_fp==NULL) {
460: safe_snprintf(smb->last_error,sizeof(smb->last_error),"msgbase not open");
461: return(SMB_ERR_NOT_OPEN);
462: }
463: if(!smb_valid_hdr_offset(smb,msg->idx.offset))
464: return(SMB_ERR_HDR_OFFSET);
465:
466: while(1) {
467: if(lock(fileno(smb->shd_fp),msg->idx.offset,sizeof(msghdr_t))==0)
468: return(SMB_SUCCESS);
469: if(!start)
470: start=time(NULL);
471: else
472: if(time(NULL)-start>=(time_t)smb->retry_time)
473: break;
474: /* In case we've already locked it */
475: if(unlock(fileno(smb->shd_fp),msg->idx.offset,sizeof(msghdr_t))!=0) {
476: SLEEP(smb->retry_delay);
477: }
478: }
479: safe_snprintf(smb->last_error,sizeof(smb->last_error),"timeout locking header");
480: return(SMB_ERR_TIMEOUT);
481: }
482:
483: /****************************************************************************/
484: /* Fills msg->idx with message index based on msg->hdr.number */
485: /* OR if msg->hdr.number is 0, based on msg->offset (record offset). */
486: /* if msg.hdr.number does not equal 0, then msg->offset is filled too. */
487: /* Either msg->hdr.number or msg->offset must be initialized before */
488: /* calling this function */
489: /* Returns 1 if message number wasn't found, 0 if it was */
490: /****************************************************************************/
491: int SMBCALL smb_getmsgidx(smb_t* smb, smbmsg_t* msg)
492: {
493: idxrec_t idx;
494: long byte_offset;
495: ulong l,total,bot,top;
496: long length;
497:
498: if(smb->sid_fp==NULL) {
499: safe_snprintf(smb->last_error,sizeof(smb->last_error),"index not open");
500: return(SMB_ERR_NOT_OPEN);
501: }
502: clearerr(smb->sid_fp);
503:
504: length=filelength(fileno(smb->sid_fp));
505: if(length<(long)sizeof(idxrec_t)) {
506: safe_snprintf(smb->last_error,sizeof(smb->last_error)
507: ,"invalid index file length: %ld",length);
508: return(SMB_ERR_FILE_LEN);
509: }
510: total=length/sizeof(idxrec_t);
511: if(!total) {
512: safe_snprintf(smb->last_error,sizeof(smb->last_error)
513: ,"invalid index file length: %ld",length);
514: return(SMB_ERR_FILE_LEN);
515: }
516:
517: if(!msg->hdr.number) {
518: if(msg->offset<0)
519: byte_offset=length-((-msg->offset)*sizeof(idxrec_t));
520: else
521: byte_offset=msg->offset*sizeof(idxrec_t);
522: if(byte_offset>=length) {
523: safe_snprintf(smb->last_error,sizeof(smb->last_error)
524: ,"invalid index offset: %ld, byte offset: %ld, length: %ld"
525: ,msg->offset, byte_offset, length);
526: return(SMB_ERR_HDR_OFFSET);
527: }
528: if(fseek(smb->sid_fp,byte_offset,SEEK_SET)) {
529: safe_snprintf(smb->last_error,sizeof(smb->last_error)
530: ,"%d '%s' seeking to offset %ld (byte %lu) in index file"
531: ,get_errno(),STRERROR(get_errno())
532: ,msg->offset,byte_offset);
533: return(SMB_ERR_SEEK);
534: }
535: if(smb_fread(smb,&msg->idx,sizeof(idxrec_t),smb->sid_fp)!=sizeof(idxrec_t)) {
536: safe_snprintf(smb->last_error,sizeof(smb->last_error)
537: ,"%d '%s' reading index at offset %ld (byte %lu)"
538: ,get_errno(),STRERROR(get_errno())
539: ,msg->offset,byte_offset);
540: return(SMB_ERR_READ);
541: }
542: /* Save the correct offset (from the beginning of the file) */
543: msg->offset=byte_offset/sizeof(idxrec_t);
544: return(SMB_SUCCESS);
545: }
546:
547: bot=0;
548: top=total;
549: l=total/2; /* Start at middle index */
550: while(1) {
551: if(l>=total) {
552: safe_snprintf(smb->last_error,sizeof(smb->last_error),"msg %lu not found"
553: ,msg->hdr.number);
554: return(SMB_ERR_NOT_FOUND);
555: }
556: if(fseek(smb->sid_fp,l*sizeof(idxrec_t),SEEK_SET)) {
557: safe_snprintf(smb->last_error,sizeof(smb->last_error)
558: ,"%d '%s' seeking to offset %lu (byte %lu) in index file"
559: ,get_errno(),STRERROR(get_errno())
560: ,l,l*sizeof(idxrec_t));
561: return(SMB_ERR_SEEK);
562: }
563: if(smb_fread(smb,&idx,sizeof(idxrec_t),smb->sid_fp)!=sizeof(idxrec_t)) {
564: safe_snprintf(smb->last_error,sizeof(smb->last_error)
565: ,"%d '%s' reading index at offset %lu (byte %lu)"
566: ,get_errno(),STRERROR(get_errno()),l,l*sizeof(idxrec_t));
567: return(SMB_ERR_READ);
568: }
569: if(bot==top-1 && idx.number!=msg->hdr.number) {
570: safe_snprintf(smb->last_error,sizeof(smb->last_error),"msg %lu not found"
571: ,msg->hdr.number);
572: return(SMB_ERR_NOT_FOUND);
573: }
574: if(idx.number>msg->hdr.number) {
575: top=l;
576: l=bot+((top-bot)/2);
577: continue;
578: }
579: if(idx.number<msg->hdr.number) {
580: bot=l;
581: l=top-((top-bot)/2);
582: continue;
583: }
584: break;
585: }
586: msg->idx=idx;
587: msg->offset=l;
588: return(SMB_SUCCESS);
589: }
590:
591: /****************************************************************************/
592: /* Reads the first index record in the open message base */
593: /****************************************************************************/
594: int SMBCALL smb_getfirstidx(smb_t* smb, idxrec_t *idx)
595: {
596: if(smb->sid_fp==NULL) {
597: safe_snprintf(smb->last_error,sizeof(smb->last_error),"index not open");
598: return(SMB_ERR_NOT_OPEN);
599: }
600: clearerr(smb->sid_fp);
601: if(fseek(smb->sid_fp,0,SEEK_SET)) {
602: safe_snprintf(smb->last_error,sizeof(smb->last_error)
603: ,"%d '%s' seeking to beginning of index file"
604: ,get_errno(),STRERROR(get_errno()));
605: return(SMB_ERR_SEEK);
606: }
607: if(smb_fread(smb,idx,sizeof(idxrec_t),smb->sid_fp)!=sizeof(idxrec_t)) {
608: safe_snprintf(smb->last_error,sizeof(smb->last_error)
609: ,"%d '%s' reading first index"
610: ,get_errno(),STRERROR(get_errno()));
611: return(SMB_ERR_READ);
612: }
613: return(SMB_SUCCESS);
614: }
615:
616: /****************************************************************************/
617: /* Reads the last index record in the open message base */
618: /****************************************************************************/
619: int SMBCALL smb_getlastidx(smb_t* smb, idxrec_t *idx)
620: {
621: long length;
622:
623: if(smb->sid_fp==NULL) {
624: safe_snprintf(smb->last_error,sizeof(smb->last_error),"index not open");
625: return(SMB_ERR_NOT_OPEN);
626: }
627: clearerr(smb->sid_fp);
628: length=filelength(fileno(smb->sid_fp));
629: if(length<(long)sizeof(idxrec_t)) {
630: safe_snprintf(smb->last_error,sizeof(smb->last_error)
631: ,"invalid index file length: %ld",length);
632: return(SMB_ERR_FILE_LEN);
633: }
634: if(fseek(smb->sid_fp,length-sizeof(idxrec_t),SEEK_SET)) {
635: safe_snprintf(smb->last_error,sizeof(smb->last_error)
636: ,"%d '%s' seeking to %u in index file"
637: ,get_errno(),STRERROR(get_errno())
638: ,(unsigned)(length-sizeof(idxrec_t)));
639: return(SMB_ERR_SEEK);
640: }
641: if(smb_fread(smb,idx,sizeof(idxrec_t),smb->sid_fp)!=sizeof(idxrec_t)) {
642: safe_snprintf(smb->last_error,sizeof(smb->last_error)
643: ,"%d '%s' reading last index"
644: ,get_errno(),STRERROR(get_errno()));
645: return(SMB_ERR_READ);
646: }
647: return(SMB_SUCCESS);
648: }
649:
650: /****************************************************************************/
651: /* Figures out the total length of the header record for 'msg' */
652: /* Returns length */
653: /****************************************************************************/
654: ulong SMBCALL smb_getmsghdrlen(smbmsg_t* msg)
655: {
656: int i;
657: ulong length;
658:
659: /* fixed portion */
660: length=sizeof(msghdr_t);
661: /* data fields */
662: length+=msg->hdr.total_dfields*sizeof(dfield_t);
663: /* header fields */
664: for(i=0;i<msg->total_hfields;i++) {
665: length+=sizeof(hfield_t);
666: length+=msg->hfield[i].length;
667: }
668: return(length);
669: }
670:
671: /****************************************************************************/
672: /* Figures out the total length of the data buffer for 'msg' */
673: /* Returns length */
674: /****************************************************************************/
675: ulong SMBCALL smb_getmsgdatlen(smbmsg_t* msg)
676: {
677: int i;
678: ulong length=0L;
679:
680: for(i=0;i<msg->hdr.total_dfields;i++)
681: length+=msg->dfield[i].length;
682: return(length);
683: }
684:
685: /****************************************************************************/
686: /* Figures out the total length of the text buffer for 'msg' */
687: /* Returns length */
688: /****************************************************************************/
689: ulong SMBCALL smb_getmsgtxtlen(smbmsg_t* msg)
690: {
691: int i;
692: ulong length=0L;
693:
694: for(i=0;i<msg->total_hfields;i++)
695: if(msg->hfield[i].type==SMB_COMMENT || msg->hfield[i].type==SMTPSYSMSG)
696: length+=msg->hfield[i].length+2;
697: for(i=0;i<msg->hdr.total_dfields;i++)
698: if(msg->dfield[i].type==TEXT_BODY || msg->dfield[i].type==TEXT_TAIL)
699: length+=msg->dfield[i].length;
700: return(length);
701: }
702:
703: static void set_convenience_ptr(smbmsg_t* msg, ushort hfield_type, void* hfield_dat)
704: {
705: switch(hfield_type) { /* convenience variables */
1.1.1.2 ! root 706: case AUTHOR:
! 707: msg->from=(char*)hfield_dat;
! 708: break;
1.1 root 709: case SENDER:
1.1.1.2 ! root 710: if(msg->from==NULL || *(msg->from)==0) {
1.1 root 711: msg->from=(char*)hfield_dat;
712: break;
713: }
714: case FORWARDED: /* fall through */
715: msg->forwarded=TRUE;
716: break;
717: case SENDERAGENT:
718: if(!msg->forwarded)
719: msg->from_agent=*(ushort *)hfield_dat;
720: break;
721: case SENDEREXT:
722: if(!msg->forwarded)
723: msg->from_ext=(char*)hfield_dat;
724: break;
725: case SENDERORG:
726: if(!msg->forwarded)
727: msg->from_org=(char*)hfield_dat;
728: break;
729: case SENDERNETTYPE:
730: if(!msg->forwarded)
731: msg->from_net.type=*(ushort *)hfield_dat;
732: break;
733: case SENDERNETADDR:
734: if(!msg->forwarded)
735: msg->from_net.addr=(char*)hfield_dat;
736: break;
1.1.1.2 ! root 737: case SENDERIPADDR:
! 738: msg->from_ip=(char*)hfield_dat;
! 739: break;
! 740: case SENDERHOSTNAME:
! 741: msg->from_host=(char*)hfield_dat;
! 742: break;
! 743: case SENDERPROTOCOL:
! 744: msg->from_prot=(char*)hfield_dat;
! 745: break;
1.1 root 746: case REPLYTO:
747: msg->replyto=(char*)hfield_dat;
748: break;
749: case REPLYTOEXT:
750: msg->replyto_ext=(char*)hfield_dat;
751: break;
752: case REPLYTOAGENT:
753: msg->replyto_agent=*(ushort *)hfield_dat;
754: break;
755: case REPLYTONETTYPE:
756: msg->replyto_net.type=*(ushort *)hfield_dat;
757: break;
758: case REPLYTONETADDR:
759: msg->replyto_net.addr=(char*)hfield_dat;
760: break;
761: case RECIPIENT:
762: msg->to=(char*)hfield_dat;
763: break;
764: case RECIPIENTEXT:
765: msg->to_ext=(char*)hfield_dat;
766: break;
767: case RECIPIENTAGENT:
768: msg->to_agent=*(ushort *)hfield_dat;
769: break;
770: case RECIPIENTNETTYPE:
771: msg->to_net.type=*(ushort *)hfield_dat;
772: break;
773: case RECIPIENTNETADDR:
774: msg->to_net.addr=(char*)hfield_dat;
775: break;
776: case SUBJECT:
777: msg->subj=(char*)hfield_dat;
778: break;
779: case SMB_SUMMARY:
780: msg->summary=(char*)hfield_dat;
781: break;
782: case SMB_EXPIRATION:
1.1.1.2 ! root 783: msg->expiration=*(uint32_t*)hfield_dat;
1.1 root 784: break;
785: case SMB_PRIORITY:
1.1.1.2 ! root 786: msg->priority=*(uint32_t*)hfield_dat;
1.1 root 787: break;
788: case SMB_COST:
1.1.1.2 ! root 789: msg->cost=*(uint32_t*)hfield_dat;
1.1 root 790: break;
791: case RFC822MSGID:
792: msg->id=(char*)hfield_dat;
793: break;
794: case RFC822REPLYID:
795: msg->reply_id=(char*)hfield_dat;
796: break;
797: case SMTPREVERSEPATH:
798: msg->reverse_path=(char*)hfield_dat;
799: break;
800: case USENETPATH:
801: msg->path=(char*)hfield_dat;
802: break;
803: case USENETNEWSGROUPS:
804: msg->newsgroups=(char*)hfield_dat;
805: break;
806: case FIDOMSGID:
807: msg->ftn_msgid=(char*)hfield_dat;
808: break;
809: case FIDOREPLYID:
810: msg->ftn_reply=(char*)hfield_dat;
811: break;
812: case FIDOAREA:
813: msg->ftn_area=(char*)hfield_dat;
814: break;
815: case FIDOPID:
816: msg->ftn_pid=(char*)hfield_dat;
817: break;
818: case FIDOTID:
819: msg->ftn_tid=(char*)hfield_dat;
820: break;
821: case FIDOFLAGS:
822: msg->ftn_flags=(char*)hfield_dat;
823: break;
824: }
825: }
826:
827: static void clear_convenience_ptrs(smbmsg_t* msg)
828: {
829: msg->from=NULL;
830: msg->from_ext=NULL;
831: msg->from_org=NULL;
1.1.1.2 ! root 832: msg->from_ip=NULL;
! 833: msg->from_host=NULL;
! 834: msg->from_prot=NULL;
1.1 root 835: memset(&msg->from_net,0,sizeof(net_t));
836:
837: msg->replyto=NULL;
838: msg->replyto_ext=NULL;
839: memset(&msg->replyto_net,0,sizeof(net_t));
840:
841: msg->to=NULL;
842: msg->to_ext=NULL;
843: memset(&msg->to_net,0,sizeof(net_t));
844:
845: msg->subj=NULL;
846: msg->summary=NULL;
847: msg->id=NULL;
848: msg->reply_id=NULL;
849: msg->reverse_path=NULL;
850: msg->path=NULL;
851: msg->newsgroups=NULL;
852:
853: msg->ftn_msgid=NULL;
854: msg->ftn_reply=NULL;
855: msg->ftn_area=NULL;
856: msg->ftn_pid=NULL;
857: msg->ftn_tid=NULL;
858: msg->ftn_flags=NULL;
859: }
860:
861: /****************************************************************************/
862: /* Read header information into 'msg' structure */
863: /* msg->idx.offset must be set before calling this function */
864: /* Must call smb_freemsgmem() to free memory allocated for var len strs */
865: /* Returns 0 on success, non-zero if error */
866: /****************************************************************************/
867: int SMBCALL smb_getmsghdr(smb_t* smb, smbmsg_t* msg)
868: {
869: void *vp,**vpp;
870: ushort i;
871: ulong l,offset;
872: idxrec_t idx;
873:
874: if(smb->shd_fp==NULL) {
875: safe_snprintf(smb->last_error,sizeof(smb->last_error),"msgbase not open");
876: return(SMB_ERR_NOT_OPEN);
877: }
878:
879: if(!smb_valid_hdr_offset(smb,msg->idx.offset))
880: return(SMB_ERR_HDR_OFFSET);
881:
882: rewind(smb->shd_fp);
883: if(fseek(smb->shd_fp,msg->idx.offset,SEEK_SET)) {
884: safe_snprintf(smb->last_error,sizeof(smb->last_error)
885: ,"%d '%s' seeking to %lu in header"
886: ,get_errno(),STRERROR(get_errno())
887: ,msg->idx.offset);
888: return(SMB_ERR_SEEK);
889: }
890:
891: idx=msg->idx;
892: offset=msg->offset;
893: memset(msg,0,sizeof(smbmsg_t));
894: msg->idx=idx;
895: msg->offset=offset;
896: if(smb_fread(smb,&msg->hdr,sizeof(msghdr_t),smb->shd_fp)!=sizeof(msghdr_t)) {
897: safe_snprintf(smb->last_error,sizeof(smb->last_error)
898: ,"%d '%s' reading msg header"
899: ,get_errno(),STRERROR(get_errno()));
900: return(SMB_ERR_READ);
901: }
902: if(memcmp(msg->hdr.id,SHD_HEADER_ID,LEN_HEADER_ID)) {
903: safe_snprintf(smb->last_error,sizeof(smb->last_error)
904: ,"corrupt message header ID: %.*s at offset %lu"
905: ,LEN_HEADER_ID,msg->hdr.id,msg->idx.offset);
906: return(SMB_ERR_HDR_ID);
907: }
908: if(msg->hdr.version<0x110) {
909: safe_snprintf(smb->last_error,sizeof(smb->last_error)
910: ,"insufficient header version: %X"
911: ,msg->hdr.version);
912: return(SMB_ERR_HDR_VER);
913: }
914: l=sizeof(msghdr_t);
915: if(msg->hdr.total_dfields && (msg->dfield
916: =(dfield_t *)malloc(sizeof(dfield_t)*msg->hdr.total_dfields))==NULL) {
917: smb_freemsgmem(msg);
918: safe_snprintf(smb->last_error,sizeof(smb->last_error)
919: ,"malloc failure of %d bytes for %d data fields"
920: ,(int)sizeof(dfield_t)*msg->hdr.total_dfields, msg->hdr.total_dfields);
921: return(SMB_ERR_MEM);
922: }
923: i=0;
924: while(i<msg->hdr.total_dfields && l<(ulong)msg->hdr.length) {
925: if(smb_fread(smb,&msg->dfield[i],sizeof(dfield_t),smb->shd_fp)!=sizeof(dfield_t)) {
926: smb_freemsgmem(msg);
927: safe_snprintf(smb->last_error,sizeof(smb->last_error)
928: ,"%d '%s' reading data field %d"
929: ,get_errno(),STRERROR(get_errno()),i);
930: return(SMB_ERR_READ);
931: }
932: i++;
933: l+=sizeof(dfield_t);
934: }
935: if(i<msg->hdr.total_dfields) {
936: smb_freemsgmem(msg);
937: safe_snprintf(smb->last_error,sizeof(smb->last_error)
938: ,"insufficient data fields read (%d instead of %d)"
939: ,i,msg->hdr.total_dfields);
940: return(SMB_ERR_READ);
941: }
942: while(l<(ulong)msg->hdr.length) {
943: i=msg->total_hfields;
944: if((vpp=(void* *)realloc(msg->hfield_dat,sizeof(void* )*(i+1)))==NULL) {
945: smb_freemsgmem(msg);
946: safe_snprintf(smb->last_error,sizeof(smb->last_error)
947: ,"realloc failure of %d bytes for header field data"
948: ,(int)sizeof(void*)*(i+1));
949: return(SMB_ERR_MEM);
950: }
951: msg->hfield_dat=vpp;
952: if((vp=(hfield_t *)realloc(msg->hfield,sizeof(hfield_t)*(i+1)))==NULL) {
953: smb_freemsgmem(msg);
954: safe_snprintf(smb->last_error,sizeof(smb->last_error)
955: ,"realloc failure of %d bytes for header fields"
956: ,(int)sizeof(hfield_t)*(i+1));
957: return(SMB_ERR_MEM);
958: }
959: msg->hfield=vp;
960: if(smb_fread(smb,&msg->hfield[i],sizeof(hfield_t),smb->shd_fp)!=sizeof(hfield_t)) {
961: smb_freemsgmem(msg);
962: safe_snprintf(smb->last_error,sizeof(smb->last_error)
963: ,"%d '%s' reading header field"
964: ,get_errno(),STRERROR(get_errno()));
965: return(SMB_ERR_READ);
966: }
967: l+=sizeof(hfield_t);
968: if((msg->hfield_dat[i]=(char*)malloc(msg->hfield[i].length+1))
969: ==NULL) { /* Allocate 1 extra for ASCIIZ terminator */
970: safe_snprintf(smb->last_error,sizeof(smb->last_error)
971: ,"malloc failure of %d bytes for header field %d"
972: ,msg->hfield[i].length+1, i);
973: smb_freemsgmem(msg); /* or 0 length field */
974: return(SMB_ERR_MEM);
975: }
976: msg->total_hfields++;
977: memset(msg->hfield_dat[i],0,msg->hfield[i].length+1); /* init to NULL */
978: if(msg->hfield[i].length
979: && smb_fread(smb,msg->hfield_dat[i],msg->hfield[i].length,smb->shd_fp)
980: !=(size_t)msg->hfield[i].length) {
981: smb_freemsgmem(msg);
982: safe_snprintf(smb->last_error,sizeof(smb->last_error)
983: ,"%d '%s' reading header field data"
984: ,get_errno(),STRERROR(get_errno()));
985: return(SMB_ERR_READ);
986: }
987: set_convenience_ptr(msg,msg->hfield[i].type,msg->hfield_dat[i]);
988:
989: l+=msg->hfield[i].length;
990: }
991:
992: /* These convenience pointers must point to something */
993: if(msg->from==NULL) msg->from=nulstr;
994: if(msg->to==NULL) msg->to=nulstr;
995: if(msg->subj==NULL) msg->subj=nulstr;
996:
997: /* If no reverse path specified, use sender's address */
998: if(msg->reverse_path == NULL && msg->from_net.type==NET_INTERNET)
999: msg->reverse_path = msg->from_net.addr;
1000:
1001: return(SMB_SUCCESS);
1002: }
1003:
1004: /****************************************************************************/
1005: /* Frees memory allocated for variable-length header fields in 'msg' */
1006: /****************************************************************************/
1007: void SMBCALL smb_freemsghdrmem(smbmsg_t* msg)
1008: {
1009: ushort i;
1010:
1011: for(i=0;i<msg->total_hfields;i++)
1012: if(msg->hfield_dat[i]) {
1013: free(msg->hfield_dat[i]);
1014: msg->hfield_dat[i]=NULL;
1015: }
1016: msg->total_hfields=0;
1017: if(msg->hfield) {
1018: free(msg->hfield);
1019: msg->hfield=NULL;
1020: }
1021: if(msg->hfield_dat) {
1022: free(msg->hfield_dat);
1023: msg->hfield_dat=NULL;
1024: }
1025: clear_convenience_ptrs(msg); /* don't leave pointers to freed memory */
1026: }
1027:
1028: /****************************************************************************/
1029: /* Frees memory allocated for 'msg' */
1030: /****************************************************************************/
1031: void SMBCALL smb_freemsgmem(smbmsg_t* msg)
1032: {
1033: if(msg->dfield) {
1034: free(msg->dfield);
1035: msg->dfield=NULL;
1036: }
1037: msg->hdr.total_dfields=0;
1038: smb_freemsghdrmem(msg);
1039: }
1040:
1041: /****************************************************************************/
1042: /* Copies memory allocated for 'srcmsg' to 'msg' */
1043: /****************************************************************************/
1044: int SMBCALL smb_copymsgmem(smb_t* smb, smbmsg_t* msg, smbmsg_t* srcmsg)
1045: {
1046: int i;
1047:
1048: memcpy(msg,srcmsg,sizeof(smbmsg_t));
1049:
1050: /* data field types/lengths */
1051: if(msg->hdr.total_dfields>0) {
1052: if((msg->dfield=(dfield_t *)malloc(msg->hdr.total_dfields*sizeof(dfield_t)))==NULL) {
1053: if(smb!=NULL)
1054: safe_snprintf(smb->last_error,sizeof(smb->last_error)
1055: ,"malloc failure of %d bytes for %d data fields"
1056: ,msg->hdr.total_dfields*sizeof(dfield_t), msg->hdr.total_dfields);
1057: return(SMB_ERR_MEM);
1058: }
1059: memcpy(msg->dfield,srcmsg->dfield,msg->hdr.total_dfields*sizeof(dfield_t));
1060: }
1061:
1062: /* header field types/lengths */
1063: if(msg->total_hfields>0) {
1064: if((msg->hfield=(hfield_t *)malloc(msg->total_hfields*sizeof(hfield_t)))==NULL) {
1065: if(smb!=NULL)
1066: safe_snprintf(smb->last_error,sizeof(smb->last_error)
1067: ,"malloc failure of %d bytes for %d header fields"
1068: ,msg->total_hfields*sizeof(hfield_t), msg->total_hfields);
1069: return(SMB_ERR_MEM);
1070: }
1071: memcpy(msg->hfield,srcmsg->hfield,msg->total_hfields*sizeof(hfield_t));
1072:
1073: /* header field data */
1074: if((msg->hfield_dat=(void**)malloc(msg->total_hfields*sizeof(void*)))==NULL) {
1075: if(smb!=NULL)
1076: safe_snprintf(smb->last_error,sizeof(smb->last_error)
1077: ,"malloc failure of %d bytes for %d header fields"
1078: ,msg->total_hfields*sizeof(void*), msg->total_hfields);
1079: return(SMB_ERR_MEM);
1080: }
1081:
1082: for(i=0;i<msg->total_hfields;i++) {
1083: if((msg->hfield_dat[i]=(void*)malloc(msg->hfield[i].length+1))==NULL) {
1084: if(smb!=NULL)
1085: safe_snprintf(smb->last_error,sizeof(smb->last_error)
1086: ,"malloc failure of %d bytes for header field #%d"
1087: ,msg->hfield[i].length+1, i+1);
1088: return(SMB_ERR_MEM);
1089: }
1090: memset(msg->hfield_dat[i],0,msg->hfield[i].length+1);
1091: memcpy(msg->hfield_dat[i],srcmsg->hfield_dat[i],msg->hfield[i].length);
1092: }
1093: }
1094:
1095: return(SMB_SUCCESS);
1096: }
1097:
1098: /****************************************************************************/
1099: /* Unlocks header for 'msg' */
1100: /****************************************************************************/
1101: int SMBCALL smb_unlockmsghdr(smb_t* smb, smbmsg_t* msg)
1102: {
1103: if(smb->shd_fp==NULL) {
1104: safe_snprintf(smb->last_error,sizeof(smb->last_error),"msgbase not open");
1105: return(SMB_ERR_NOT_OPEN);
1106: }
1107: if(!smb_valid_hdr_offset(smb,msg->idx.offset))
1108: return(SMB_ERR_HDR_OFFSET);
1109: return(unlock(fileno(smb->shd_fp),msg->idx.offset,sizeof(msghdr_t)));
1110: }
1111:
1112:
1113: /****************************************************************************/
1114: /* Adds a header field to the 'msg' structure (in memory only) */
1115: /****************************************************************************/
1.1.1.2 ! root 1116: int SMBCALL smb_hfield_add(smbmsg_t* msg, ushort type, size_t length, void* data, BOOL insert)
1.1 root 1117: {
1118: void** vpp;
1119: hfield_t* hp;
1120: int i;
1121:
1122: if(smb_getmsghdrlen(msg)+sizeof(hfield_t)+length>SMB_MAX_HDR_LEN)
1123: return(SMB_ERR_HDR_LEN);
1124:
1125: i=msg->total_hfields;
1126: if((hp=(hfield_t *)realloc(msg->hfield,sizeof(hfield_t)*(i+1)))==NULL)
1127: return(SMB_ERR_MEM);
1128: msg->hfield=hp;
1.1.1.2 ! root 1129:
1.1 root 1130: if((vpp=(void* *)realloc(msg->hfield_dat,sizeof(void* )*(i+1)))==NULL)
1131: return(SMB_ERR_MEM);
1132: msg->hfield_dat=vpp;
1.1.1.2 ! root 1133:
! 1134: if(insert) {
! 1135: memmove(msg->hfield+1, msg->hfield, sizeof(hfield_t)*i);
! 1136: memmove(msg->hfield_dat+1, msg->hfield_dat, sizeof(void*)*i);
! 1137: i=0;
! 1138: }
1.1 root 1139: msg->total_hfields++;
1140: msg->hfield[i].type=type;
1141: msg->hfield[i].length=length;
1142: if(length) {
1143: if((msg->hfield_dat[i]=(void* )malloc(length+1))==NULL)
1144: return(SMB_ERR_MEM); /* Allocate 1 extra for ASCIIZ terminator */
1145: memset(msg->hfield_dat[i],0,length+1);
1146: memcpy(msg->hfield_dat[i],data,length);
1147: set_convenience_ptr(msg,type,msg->hfield_dat[i]);
1148: }
1149: else
1150: msg->hfield_dat[i]=NULL;
1151:
1152: return(SMB_SUCCESS);
1153: }
1154:
1155: /****************************************************************************/
1156: /* Adds a list of header fields to the 'msg' structure (in memory only) */
1157: /****************************************************************************/
1.1.1.2 ! root 1158: int SMBCALL smb_hfield_add_list(smbmsg_t* msg, hfield_t** hfield_list, void** hfield_dat, BOOL insert)
1.1 root 1159: {
1160: int retval;
1161: unsigned n;
1162:
1163: if(hfield_list==NULL)
1164: return(SMB_FAILURE);
1165:
1166: for(n=0;hfield_list[n]!=NULL;n++)
1.1.1.2 ! root 1167: if((retval=smb_hfield_add(msg
! 1168: ,hfield_list[n]->type,hfield_list[n]->length,hfield_dat[n],insert))!=SMB_SUCCESS)
1.1 root 1169: return(retval);
1170:
1171: return(SMB_SUCCESS);
1172: }
1173:
1174: /****************************************************************************/
1175: /* Convenience function to add an ASCIIZ string header field */
1176: /****************************************************************************/
1.1.1.2 ! root 1177: int SMBCALL smb_hfield_add_str(smbmsg_t* msg, ushort type, const char* str, BOOL insert)
1.1 root 1178: {
1.1.1.2 ! root 1179: return smb_hfield_add(msg, type, str==NULL ? 0:strlen(str), (void*)str, insert);
1.1 root 1180: }
1181:
1182: /****************************************************************************/
1183: /* Convenience function to add an ASCIIZ string header field */
1184: /****************************************************************************/
1.1.1.2 ! root 1185: int SMBCALL smb_hfield_add_netaddr(smbmsg_t* msg, ushort type, const char* str, ushort* nettype, BOOL insert)
1.1 root 1186: {
1187: fidoaddr_t sys_addr = {0,0,0,0}; /* replace unspecified fields with 0 (don't assume 1:1/1) */
1188: fidoaddr_t fidoaddr;
1189: ushort tmp_nettype=NET_UNKNOWN;
1190:
1191: if(nettype==NULL)
1192: nettype=&tmp_nettype;
1193: if(*nettype==NET_UNKNOWN)
1194: *nettype=smb_netaddr_type(str);
1195: if(*nettype==NET_FIDO) {
1196: fidoaddr=smb_atofaddr(&sys_addr,str);
1.1.1.2 ! root 1197: return smb_hfield_add(msg,type,sizeof(fidoaddr),&fidoaddr,insert);
1.1 root 1198: } else
1.1.1.2 ! root 1199: return smb_hfield_add_str(msg,type,str,insert);
1.1 root 1200: }
1201:
1202: /****************************************************************************/
1203: /* Appends data to an existing header field (in memory only) */
1204: /****************************************************************************/
1205: int SMBCALL smb_hfield_append(smbmsg_t* msg, ushort type, size_t length, void* data)
1206: {
1207: int i;
1208: BYTE* p;
1209:
1210: if(length==0) /* nothing to append */
1211: return(SMB_SUCCESS);
1212:
1213: if(msg->total_hfields<1)
1214: return(SMB_ERR_NOT_FOUND);
1215:
1216: /* search for the last header field of this type */
1217: for(i=msg->total_hfields-1;i>=0;i--)
1218: if(msg->hfield[i].type == type)
1219: break;
1220: if(i<0)
1221: return(SMB_ERR_NOT_FOUND);
1222:
1223: if(smb_getmsghdrlen(msg)+length>SMB_MAX_HDR_LEN)
1224: return(SMB_ERR_HDR_LEN);
1225:
1226: if((p=(BYTE*)realloc(msg->hfield_dat[i],msg->hfield[i].length+length+1))==NULL)
1227: return(SMB_ERR_MEM); /* Allocate 1 extra for ASCIIZ terminator */
1228:
1229: msg->hfield_dat[i]=p;
1230: p+=msg->hfield[i].length; /* skip existing data */
1231: memset(p,0,length+1);
1232: memcpy(p,data,length); /* append */
1233: msg->hfield[i].length+=length;
1234: set_convenience_ptr(msg,type,msg->hfield_dat[i]);
1235:
1236: return(SMB_SUCCESS);
1237: }
1238:
1239: /****************************************************************************/
1240: /* Appends data to an existing ASCIIZ header field (in memory only) */
1241: /****************************************************************************/
1242: int SMBCALL smb_hfield_append_str(smbmsg_t* msg, ushort type, const char* str)
1243: {
1.1.1.2 ! root 1244: return smb_hfield_append(msg, type, str==NULL ? 0:strlen(str), (void*)str);
! 1245: }
! 1246:
! 1247: /****************************************************************************/
! 1248: /* Replaces an header field value (in memory only) */
! 1249: /****************************************************************************/
! 1250: int SMBCALL smb_hfield_replace(smbmsg_t* msg, ushort type, size_t length, void* data)
! 1251: {
! 1252: int i;
! 1253: void* p;
! 1254:
! 1255: if(msg->total_hfields<1)
! 1256: return(SMB_ERR_NOT_FOUND);
! 1257:
! 1258: /* search for the last header field of this type */
! 1259: for(i=msg->total_hfields-1;i>=0;i--)
! 1260: if(msg->hfield[i].type == type)
! 1261: break;
! 1262: if(i<0)
! 1263: return(SMB_ERR_NOT_FOUND);
! 1264:
! 1265: if((p=(BYTE*)realloc(msg->hfield_dat[i],length+1))==NULL)
! 1266: return(SMB_ERR_MEM); /* Allocate 1 extra for ASCIIZ terminator */
! 1267:
! 1268: msg->hfield_dat[i]=p;
! 1269: memset(p,0,length+1);
! 1270: memcpy(p,data,length);
! 1271: msg->hfield[i].length=length;
! 1272: set_convenience_ptr(msg,type,msg->hfield_dat[i]);
! 1273:
! 1274: return SMB_SUCCESS;
! 1275: }
! 1276:
! 1277: /****************************************************************************/
! 1278: /* Replace an existing ASCIIZ header field value (in memory only) */
! 1279: /****************************************************************************/
! 1280: int SMBCALL smb_hfield_replace_str(smbmsg_t* msg, ushort type, const char* str)
! 1281: {
! 1282: return smb_hfield_replace(msg, type, str==NULL ? 0:strlen(str), (void*)str);
1.1 root 1283: }
1284:
1285: /****************************************************************************/
1286: /* Searches for a specific header field (by type) and returns it */
1287: /****************************************************************************/
1288: void* SMBCALL smb_get_hfield(smbmsg_t* msg, ushort type, hfield_t* hfield)
1289: {
1290: int i;
1291:
1292: for(i=0;i<msg->total_hfields;i++)
1293: if(msg->hfield[i].type == type) {
1294: if(hfield != NULL)
1295: *hfield = msg->hfield[i];
1296: return(msg->hfield_dat[i]);
1297: }
1298:
1299: return(NULL);
1300: }
1301:
1302: /****************************************************************************/
1303: /* Adds a data field to the 'msg' structure (in memory only) */
1304: /* Automatically figures out the offset into the data buffer from existing */
1305: /* dfield lengths */
1306: /****************************************************************************/
1307: int SMBCALL smb_dfield(smbmsg_t* msg, ushort type, ulong length)
1308: {
1309: dfield_t* dp;
1310: int i,j;
1311:
1312: i=msg->hdr.total_dfields;
1313: if((dp=(dfield_t *)realloc(msg->dfield,sizeof(dfield_t)*(i+1)))==NULL)
1314: return(SMB_ERR_MEM);
1315:
1316: msg->dfield=dp;
1317: msg->hdr.total_dfields++;
1318: msg->dfield[i].type=type;
1319: msg->dfield[i].length=length;
1320: for(j=msg->dfield[i].offset=0;j<i;j++)
1321: msg->dfield[i].offset+=msg->dfield[j].length;
1322: return(SMB_SUCCESS);
1323: }
1324:
1325: /****************************************************************************/
1326: /* Checks CRC history file for duplicate crc. If found, returns 1. */
1327: /* If no dupe, adds to CRC history and returns 0, or negative if error. */
1328: /****************************************************************************/
1.1.1.2 ! root 1329: int SMBCALL smb_addcrc(smb_t* smb, uint32_t crc)
1.1 root 1330: {
1331: char str[MAX_PATH+1];
1332: int file;
1333: int wr;
1334: long length;
1335: long newlen;
1.1.1.2 ! root 1336: ulong l;
! 1337: uint32_t *buf;
1.1 root 1338: time_t start=0;
1339:
1340: if(!smb->status.max_crcs)
1341: return(SMB_SUCCESS);
1342:
1343: SAFEPRINTF(str,"%s.sch",smb->file);
1344: while(1) {
1345: if((file=sopen(str,O_RDWR|O_CREAT|O_BINARY,SH_DENYRW,S_IREAD|S_IWRITE))!=-1)
1346: break;
1347: if(get_errno()!=EACCES && get_errno()!=EAGAIN) {
1348: safe_snprintf(smb->last_error,sizeof(smb->last_error)
1349: ,"%d '%s' opening %s"
1350: ,get_errno(),STRERROR(get_errno()),str);
1351: return(SMB_ERR_OPEN);
1352: }
1353: if(!start)
1354: start=time(NULL);
1355: else
1356: if(time(NULL)-start>=(time_t)smb->retry_time) {
1357: safe_snprintf(smb->last_error,sizeof(smb->last_error)
1358: ,"timeout opening %s (retry_time=%ld)"
1359: ,str,smb->retry_time);
1360: return(SMB_ERR_TIMEOUT);
1361: }
1362: SLEEP(smb->retry_delay);
1363: }
1364:
1365: length=filelength(file);
1.1.1.2 ! root 1366: if(length<0L || length%sizeof(uint32_t)) {
1.1 root 1367: close(file);
1368: safe_snprintf(smb->last_error,sizeof(smb->last_error)
1369: ,"invalid file length: %ld", length);
1370: return(SMB_ERR_FILE_LEN);
1371: }
1372:
1373: if(length!=0) {
1.1.1.2 ! root 1374: if((buf=(uint32_t*)malloc(length))==NULL) {
1.1 root 1375: close(file);
1376: safe_snprintf(smb->last_error,sizeof(smb->last_error)
1377: ,"malloc failure of %ld bytes"
1378: ,length);
1379: return(SMB_ERR_MEM);
1380: }
1381:
1382: if(read(file,buf,length)!=length) {
1383: close(file);
1384: free(buf);
1385: safe_snprintf(smb->last_error,sizeof(smb->last_error)
1386: ,"%d '%s' reading %ld bytes"
1387: ,get_errno(),STRERROR(get_errno()),length);
1388: return(SMB_ERR_READ);
1389: }
1390:
1.1.1.2 ! root 1391: for(l=0;l<length/sizeof(int32_t);l++)
1.1 root 1392: if(crc==buf[l])
1393: break;
1.1.1.2 ! root 1394: if(l<length/sizeof(int32_t)) { /* Dupe CRC found */
1.1 root 1395: close(file);
1396: free(buf);
1397: safe_snprintf(smb->last_error,sizeof(smb->last_error)
1398: ,"duplicate message text CRC detected");
1399: return(SMB_DUPE_MSG);
1400: }
1401:
1.1.1.2 ! root 1402: if(length>=(long)(smb->status.max_crcs*sizeof(int32_t))) {
! 1403: newlen=(smb->status.max_crcs-1)*sizeof(int32_t);
1.1 root 1404: chsize(file,0); /* truncate it */
1405: lseek(file,0L,SEEK_SET);
1406: write(file,buf+(length-newlen),newlen);
1407: }
1408: free(buf);
1409: }
1410: wr=write(file,&crc,sizeof(crc)); /* Write to the end */
1411: close(file);
1412:
1413: if(wr!=sizeof(crc)) {
1414: safe_snprintf(smb->last_error,sizeof(smb->last_error)
1415: ,"%d '%s' writing %u bytes"
1416: ,get_errno(),STRERROR(get_errno()),sizeof(crc));
1417: return(SMB_ERR_WRITE);
1418: }
1419:
1420: return(SMB_SUCCESS);
1421: }
1422:
1423: /****************************************************************************/
1424: /* Creates a new message header record in the header file. */
1425: /* If storage is SMB_SELFPACK, self-packing conservative allocation is used */
1426: /* If storage is SMB_FASTALLOC, fast allocation is used */
1427: /* If storage is SMB_HYPERALLOC, no allocation tables are used (fastest) */
1428: /* This function will UN-lock the SMB header */
1429: /****************************************************************************/
1430: int SMBCALL smb_addmsghdr(smb_t* smb, smbmsg_t* msg, int storage)
1431: {
1432: int i;
1433: long l;
1434: ulong hdrlen;
1435:
1436: if(smb->shd_fp==NULL) {
1437: safe_snprintf(smb->last_error,sizeof(smb->last_error),"msgbase not open");
1438: return(SMB_ERR_NOT_OPEN);
1439: }
1440:
1441: if(!smb->locked && smb_locksmbhdr(smb)!=SMB_SUCCESS)
1442: return(SMB_ERR_LOCK);
1443:
1444: hdrlen=smb_getmsghdrlen(msg);
1445: if(hdrlen>SMB_MAX_HDR_LEN) { /* headers are limited to 64k in size */
1446: smb_unlocksmbhdr(smb);
1447: safe_snprintf(smb->last_error,sizeof(smb->last_error)
1448: ,"illegal message header length (%lu > %u)"
1449: ,hdrlen,SMB_MAX_HDR_LEN);
1450: return(SMB_ERR_HDR_LEN);
1451: }
1452:
1453: if((i=smb_getstatus(smb))!=SMB_SUCCESS) {
1454: smb_unlocksmbhdr(smb);
1455: return(i);
1456: }
1457: msg->hdr.number=smb->status.last_msg+1;
1458:
1459: /* This is *not* a dupe-check */
1460: if(!(msg->flags&MSG_FLAG_HASHED) /* not already hashed */
1.1.1.2 ! root 1461: && (i=smb_hashmsg(smb,msg,/* text: */NULL,/* update? */TRUE))!=SMB_SUCCESS) {
1.1 root 1462: smb_unlocksmbhdr(smb);
1463: return(i); /* error updating hash table */
1464: }
1465:
1466: if(storage!=SMB_HYPERALLOC && (i=smb_open_ha(smb))!=SMB_SUCCESS) {
1467: smb_unlocksmbhdr(smb);
1468: return(i);
1469: }
1470:
1471: if(msg->hdr.version==0)
1472: msg->hdr.version=SMB_VERSION;
1473: msg->hdr.length=(ushort)hdrlen;
1474: if(storage==SMB_HYPERALLOC)
1475: l=smb_hallochdr(smb);
1476: else if(storage==SMB_FASTALLOC)
1477: l=smb_fallochdr(smb,msg->hdr.length);
1478: else
1479: l=smb_allochdr(smb,msg->hdr.length);
1480: if(storage!=SMB_HYPERALLOC)
1481: smb_close_ha(smb);
1482: if(l<0) {
1483: smb_unlocksmbhdr(smb);
1484: return(l);
1485: }
1486:
1487: msg->idx.offset=smb->status.header_offset+l;
1488: msg->offset=smb->status.total_msgs;
1489: i=smb_putmsg(smb,msg);
1490: if(i==SMB_SUCCESS) {
1491: smb->status.last_msg++;
1492: smb->status.total_msgs++;
1493: smb_putstatus(smb);
1494: }
1495: smb_unlocksmbhdr(smb);
1496: return(i);
1497: }
1498:
1499: /****************************************************************************/
1500: /* Safely updates existing index and header records for msg */
1501: /* Nothing should be locked prior to calling this function and nothing */
1502: /* should (normally) be locked when it exits */
1503: /****************************************************************************/
1504: int SMBCALL smb_updatemsg(smb_t* smb, smbmsg_t* msg)
1505: {
1506: int retval;
1507:
1508: /* Insure no one else can be changing the index at this time */
1509: if((retval=smb_locksmbhdr(smb))!=SMB_SUCCESS)
1510: return(retval);
1511: /* Get the current index record offset (for later update by smb_putmsgidx) */
1512: if((retval=smb_getmsgidx(smb, msg))==SMB_SUCCESS) {
1513: /* Don't let any one else read or write this header while we're updating it */
1514: if((retval=smb_lockmsghdr(smb,msg))==SMB_SUCCESS) {
1515: retval=smb_putmsg(smb,msg);
1516: smb_unlockmsghdr(smb,msg);
1517: }
1518: }
1519: smb_unlocksmbhdr(smb);
1520: return(retval);
1521: }
1522:
1523: /****************************************************************************/
1524: /* Writes both header and index information for msg 'msg' */
1525: /****************************************************************************/
1526: int SMBCALL smb_putmsg(smb_t* smb, smbmsg_t* msg)
1527: {
1528: int i;
1529:
1530: smb_init_idx(smb,msg);
1531:
1532: if((i=smb_putmsghdr(smb,msg))!=SMB_SUCCESS)
1533: return(i);
1534:
1535: return(smb_putmsgidx(smb,msg));
1536: }
1537:
1538: /****************************************************************************/
1539: /* Initializes/re-synchronizes all the fields of the message index record */
1540: /* with the values from the message header (except for the header offset) */
1541: /****************************************************************************/
1542: int SMBCALL smb_init_idx(smb_t* smb, smbmsg_t* msg)
1543: {
1544: msg->idx.subj=smb_subject_crc(msg->subj);
1545:
1546: if(smb->status.attr&SMB_EMAIL) {
1547: if(msg->to_ext)
1548: msg->idx.to=atoi(msg->to_ext);
1549: else
1550: msg->idx.to=0;
1551: if(msg->from_ext)
1552: msg->idx.from=atoi(msg->from_ext);
1553: else
1554: msg->idx.from=0;
1555: } else {
1556: msg->idx.to=smb_name_crc(msg->to);
1557: msg->idx.from=smb_name_crc(msg->from);
1558: }
1559:
1560: /* Make sure these index/header fields are always *nsync */
1561: msg->idx.number = msg->hdr.number;
1562: msg->idx.attr = msg->hdr.attr;
1563: msg->idx.time = msg->hdr.when_imported.time;
1564:
1565: return(SMB_SUCCESS);
1566: }
1567:
1568: /****************************************************************************/
1569: /* Writes index information for 'msg' */
1570: /* msg->idx */
1571: /* and msg->offset must be set prior to calling to this function */
1572: /* Returns 0 if everything ok */
1573: /****************************************************************************/
1574: int SMBCALL smb_putmsgidx(smb_t* smb, smbmsg_t* msg)
1575: {
1576: long length;
1577:
1578: if(smb->sid_fp==NULL) {
1579: safe_snprintf(smb->last_error,sizeof(smb->last_error),"index not open");
1580: return(SMB_ERR_NOT_OPEN);
1581: }
1582: clearerr(smb->sid_fp);
1583: length = filelength(fileno(smb->sid_fp));
1584: if(length < (long)(msg->offset*sizeof(idxrec_t))) {
1585: safe_snprintf(smb->last_error,sizeof(smb->last_error)
1586: ,"invalid index offset: %ld, byte offset: %lu, length: %lu"
1587: ,msg->offset, msg->offset*sizeof(idxrec_t), length);
1588: return(SMB_ERR_HDR_OFFSET);
1589: }
1590: if(fseek(smb->sid_fp,msg->offset*sizeof(idxrec_t),SEEK_SET)) {
1591: safe_snprintf(smb->last_error,sizeof(smb->last_error)
1592: ,"%d '%s' seeking to %u in header"
1593: ,get_errno(),STRERROR(get_errno())
1594: ,(unsigned)(msg->offset*sizeof(idxrec_t)));
1595: return(SMB_ERR_SEEK);
1596: }
1597: if(!fwrite(&msg->idx,sizeof(idxrec_t),1,smb->sid_fp)) {
1598: safe_snprintf(smb->last_error,sizeof(smb->last_error)
1599: ,"%d '%s' writing index"
1600: ,get_errno(),STRERROR(get_errno()));
1601: return(SMB_ERR_WRITE);
1602: }
1603: return fflush(smb->sid_fp); /* SMB_SUCCESS == 0 */
1604: }
1605:
1606: /****************************************************************************/
1607: /* Writes header information for 'msg' */
1608: /* msg->hdr.length */
1609: /* msg->idx.offset */
1610: /* and msg->offset must be set prior to calling to this function */
1611: /* Returns 0 if everything ok */
1612: /****************************************************************************/
1613: int SMBCALL smb_putmsghdr(smb_t* smb, smbmsg_t* msg)
1614: {
1615: ushort i;
1616: ulong hdrlen;
1617:
1618: if(smb->shd_fp==NULL) {
1619: safe_snprintf(smb->last_error,sizeof(smb->last_error),"msgbase not open");
1620: return(SMB_ERR_NOT_OPEN);
1621: }
1622:
1623: if(!smb_valid_hdr_offset(smb,msg->idx.offset))
1624: return(SMB_ERR_HDR_OFFSET);
1625:
1626: clearerr(smb->shd_fp);
1627: if(fseek(smb->shd_fp,msg->idx.offset,SEEK_SET)) {
1628: safe_snprintf(smb->last_error,sizeof(smb->last_error)
1629: ,"%d '%s' seeking to %lu in index"
1630: ,get_errno(),STRERROR(get_errno()),msg->idx.offset);
1631: return(SMB_ERR_SEEK);
1632: }
1633: /* Verify that the number of blocks required to stored the actual
1634: (calculated) header length does not exceed the number allocated. */
1635: hdrlen=smb_getmsghdrlen(msg);
1636: if(hdrlen>SMB_MAX_HDR_LEN) { /* headers are limited to 64k in size */
1637: safe_snprintf(smb->last_error,sizeof(smb->last_error)
1638: ,"illegal message header length (%lu > %u)"
1639: ,hdrlen,SMB_MAX_HDR_LEN);
1640: return(SMB_ERR_HDR_LEN);
1641: }
1642: if(smb_hdrblocks(hdrlen) > smb_hdrblocks(msg->hdr.length)) {
1643: safe_snprintf(smb->last_error,sizeof(smb->last_error)
1644: ,"illegal header length increase: %lu (%lu blocks) vs %hu (%lu blocks)"
1645: ,hdrlen, smb_hdrblocks(hdrlen)
1646: ,msg->hdr.length, smb_hdrblocks(msg->hdr.length));
1647: return(SMB_ERR_HDR_LEN);
1648: }
1649: msg->hdr.length=(ushort)hdrlen; /* store the actual header length */
1650: /**********************************/
1651: /* Set the message header ID here */
1652: /**********************************/
1653: memcpy(&msg->hdr.id,SHD_HEADER_ID,LEN_HEADER_ID);
1654:
1655: /************************************************/
1656: /* Write the fixed portion of the header record */
1657: /************************************************/
1658: if(!fwrite(&msg->hdr,sizeof(msghdr_t),1,smb->shd_fp)) {
1659: safe_snprintf(smb->last_error,sizeof(smb->last_error)
1660: ,"%d '%s' writing fixed portion of header record"
1661: ,get_errno(),STRERROR(get_errno()));
1662: return(SMB_ERR_WRITE);
1663: }
1664:
1665: /************************************************/
1666: /* Write the data fields (each is fixed length) */
1667: /************************************************/
1668: for(i=0;i<msg->hdr.total_dfields;i++)
1669: if(!fwrite(&msg->dfield[i],sizeof(dfield_t),1,smb->shd_fp)) {
1670: safe_snprintf(smb->last_error,sizeof(smb->last_error)
1671: ,"%d '%s' writing data field"
1672: ,get_errno(),STRERROR(get_errno()));
1673: return(SMB_ERR_WRITE);
1674: }
1675: /*******************************************/
1676: /* Write the variable length header fields */
1677: /*******************************************/
1678: for(i=0;i<msg->total_hfields;i++) {
1679: if(!fwrite(&msg->hfield[i],sizeof(hfield_t),1,smb->shd_fp)) {
1680: safe_snprintf(smb->last_error,sizeof(smb->last_error)
1681: ,"%d '%s' writing header field"
1682: ,get_errno(),STRERROR(get_errno()));
1683: return(SMB_ERR_WRITE);
1684: }
1685: if(msg->hfield[i].length /* more then 0 bytes long */
1686: && !fwrite(msg->hfield_dat[i],msg->hfield[i].length,1,smb->shd_fp)) {
1687: safe_snprintf(smb->last_error,sizeof(smb->last_error)
1688: ,"%d '%s' writing header field data"
1689: ,get_errno(),STRERROR(get_errno()));
1690: return(SMB_ERR_WRITE);
1691: }
1692: }
1693:
1694: while(hdrlen%SHD_BLOCK_LEN) {
1695: if(fputc(0,smb->shd_fp)!=0) {
1696: safe_snprintf(smb->last_error,sizeof(smb->last_error)
1697: ,"%d '%s' padding header block"
1698: ,get_errno(),STRERROR(get_errno()));
1699: return(SMB_ERR_WRITE); /* pad block with NULL */
1700: }
1701: hdrlen++;
1702: }
1703: return fflush(smb->shd_fp); /* SMB_SUCCESS == 0 */
1704: }
1705:
1706: /****************************************************************************/
1707: /* Creates a sub-board's initial header file */
1708: /* Truncates and deletes other associated SMB files */
1709: /****************************************************************************/
1710: int SMBCALL smb_create(smb_t* smb)
1711: {
1712: char str[MAX_PATH+1];
1713: smbhdr_t hdr;
1714:
1715: if(smb->shd_fp==NULL || smb->sdt_fp==NULL || smb->sid_fp==NULL) {
1716: safe_snprintf(smb->last_error,sizeof(smb->last_error),"msgbase not open");
1717: return(SMB_ERR_NOT_OPEN);
1718: }
1719: if(filelength(fileno(smb->shd_fp))>=(long)(sizeof(smbhdr_t)+sizeof(smbstatus_t))
1720: && smb_locksmbhdr(smb)!=SMB_SUCCESS) /* header exists, so lock it */
1721: return(SMB_ERR_LOCK);
1722: memset(&hdr,0,sizeof(smbhdr_t));
1723: memcpy(hdr.id,SMB_HEADER_ID,LEN_HEADER_ID);
1724: hdr.version=SMB_VERSION;
1725: hdr.length=sizeof(smbhdr_t)+sizeof(smbstatus_t);
1726: smb->status.last_msg=smb->status.total_msgs=0;
1727: smb->status.header_offset=sizeof(smbhdr_t)+sizeof(smbstatus_t);
1728: rewind(smb->shd_fp);
1729: fwrite(&hdr,1,sizeof(smbhdr_t),smb->shd_fp);
1730: fwrite(&(smb->status),1,sizeof(smbstatus_t),smb->shd_fp);
1731: rewind(smb->shd_fp);
1732: chsize(fileno(smb->shd_fp),sizeof(smbhdr_t)+sizeof(smbstatus_t));
1733: fflush(smb->shd_fp);
1734:
1735: rewind(smb->sdt_fp);
1736: chsize(fileno(smb->sdt_fp),0L);
1737: rewind(smb->sid_fp);
1738: chsize(fileno(smb->sid_fp),0L);
1739:
1740: SAFEPRINTF(str,"%s.sda",smb->file);
1741: remove(str); /* if it exists, delete it */
1742: SAFEPRINTF(str,"%s.sha",smb->file);
1743: remove(str); /* if it exists, delete it */
1744: SAFEPRINTF(str,"%s.sch",smb->file);
1745: remove(str);
1746: SAFEPRINTF(str,"%s.hash",smb->file);
1747: remove(str);
1748: smb_unlocksmbhdr(smb);
1749: return(SMB_SUCCESS);
1750: }
1751:
1752: /****************************************************************************/
1753: /* Returns number of data blocks required to store "length" amount of data */
1754: /****************************************************************************/
1755: ulong SMBCALL smb_datblocks(ulong length)
1756: {
1757: ulong blocks;
1758:
1759: blocks=length/SDT_BLOCK_LEN;
1760: if(length%SDT_BLOCK_LEN)
1761: blocks++;
1762: return(blocks);
1763: }
1764:
1765: /****************************************************************************/
1766: /* Returns number of header blocks required to store "length" size header */
1767: /****************************************************************************/
1768: ulong SMBCALL smb_hdrblocks(ulong length)
1769: {
1770: ulong blocks;
1771:
1772: blocks=length/SHD_BLOCK_LEN;
1773: if(length%SHD_BLOCK_LEN)
1774: blocks++;
1775: return(blocks);
1776: }
1777:
1778: /****************************************************************************/
1779: /* Returns difference from specified timezone and UTC/GMT */
1780: /****************************************************************************/
1781: int SMBCALL smb_tzutc(short zone)
1782: {
1783: int tz;
1784:
1785: if(OTHER_ZONE(zone))
1786: return(zone);
1787:
1788: tz=zone&0xfff;
1789: if(zone&(WESTERN_ZONE|US_ZONE)) { /* West of UTC? */
1790: if(zone&DAYLIGHT)
1.1.1.2 ! root 1791: tz-=60; /* ToDo: Daylight Saving Time adjustment is *not* always +60 minutes */
1.1 root 1792: return(-tz);
1793: }
1794: return(tz);
1795: }
1796:
1797: /****************************************************************************/
1798: /****************************************************************************/
1799: int SMBCALL smb_updatethread(smb_t* smb, smbmsg_t* remsg, ulong newmsgnum)
1800: {
1801: int retval=SMB_ERR_NOT_FOUND;
1802: ulong nextmsgnum;
1803: smbmsg_t nextmsg;
1804:
1805: if(!remsg->hdr.thread_first) { /* New msg is first reply */
1806: if(remsg->idx.offset==0 /* index not read? */
1807: && (retval=smb_getmsgidx(smb,remsg))!=SMB_SUCCESS)
1808: return(retval);
1809: if((retval=smb_lockmsghdr(smb,remsg))!=SMB_SUCCESS)
1810: return(retval);
1811: if(!remsg->hdr.length /* header not read? */
1812: && (retval=smb_getmsghdr(smb,remsg))!=SMB_SUCCESS)
1813: return(retval);
1814:
1815: remsg->hdr.thread_first=newmsgnum;
1816: retval=smb_putmsghdr(smb,remsg);
1817: smb_unlockmsghdr(smb,remsg);
1818: return(retval);
1819: }
1820:
1821: /* Search for last reply and extend chain */
1822: memset(&nextmsg,0,sizeof(nextmsg));
1823: nextmsgnum=remsg->hdr.thread_first; /* start with first reply */
1824:
1825: while(1) {
1826: nextmsg.idx.offset=0;
1827: nextmsg.hdr.number=nextmsgnum;
1828: if(smb_getmsgidx(smb, &nextmsg)!=SMB_SUCCESS) /* invalid thread origin */
1829: break;
1830: if(smb_lockmsghdr(smb,&nextmsg)!=SMB_SUCCESS)
1831: break;
1832: if(smb_getmsghdr(smb, &nextmsg)!=SMB_SUCCESS) {
1833: smb_unlockmsghdr(smb,&nextmsg);
1834: break;
1835: }
1836: if(nextmsg.hdr.thread_next && nextmsg.hdr.thread_next!=nextmsgnum) {
1837: nextmsgnum=nextmsg.hdr.thread_next;
1838: smb_unlockmsghdr(smb,&nextmsg);
1839: smb_freemsgmem(&nextmsg);
1840: continue;
1841: }
1842: nextmsg.hdr.thread_next=newmsgnum;
1843: retval=smb_putmsghdr(smb,&nextmsg);
1844: smb_unlockmsghdr(smb,&nextmsg);
1845: smb_freemsgmem(&nextmsg);
1846: break;
1847: }
1848:
1849: return(retval);
1850: }
1851:
1852: /* End of SMBLIB.C */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.