1 /***************************************************************************
2  *                                                                         *
3  *  Squish Developers Kit Source, Version 2.00                             *
4  *  Copyright 1989-1994 by SCI Communications.  All rights reserved.       *
5  *                                                                         *
6  *  USE OF THIS FILE IS SUBJECT TO THE RESTRICTIONS CONTAINED IN THE       *
7  *  SQUISH DEVELOPERS KIT LICENSING AGREEMENT IN SQDEV.PRN.  IF YOU DO NOT *
8  *  FIND THE TEXT OF THIS AGREEMENT IN THE AFOREMENTIONED FILE, OR IF YOU  *
9  *  DO NOT HAVE THIS FILE, YOU SHOULD IMMEDIATELY CONTACT THE AUTHOR AT    *
10  *  ONE OF THE ADDRESSES LISTED BELOW.  IN NO EVENT SHOULD YOU PROCEED TO  *
11  *  USE THIS FILE WITHOUT HAVING ACCEPTED THE TERMS OF THE SQUISH          *
12  *  DEVELOPERS KIT LICENSING AGREEMENT, OR SUCH OTHER AGREEMENT AS YOU ARE *
13  *  ABLE TO REACH WITH THE AUTHOR.                                         *
14  *                                                                         *
15  *  You can contact the author at one of the address listed below:         *
16  *                                                                         *
17  *  Scott Dudley       FidoNet     1:249/106                               *
18  *  777 Downing St.    Internet    sjd@f106.n249.z1.fidonet.org            *
19  *  Kingston, Ont.     CompuServe  >INTERNET:sjd@f106.n249.z1.fidonet.org  *
20  *  Canada  K7M 5N3    BBS         1-613-634-3058, V.32bis                 *
21  *                                                                         *
22  ***************************************************************************/
23 
24 /* $Id$ */
25 
26 #ifndef __API_SQ_H_DEFINED
27 #define __API_SQ_H_DEFINED
28 
29 #include <huskylib/compiler.h>
30 
31 #include "msgapi.h"
32 
33 struct _sqhdr;
34 struct _sqidx;
35 
36 typedef struct _sqidx SQIDX;
37 typedef struct _sqhdr SQHDR;
38 typedef hSINT32 FOFS;
39 
40 
41 /* Try to access a locked Squish base up to five times */
42 
43 #define SQUISH_LOCK_RETRY 5
44 
45 
46 /* Expand the Squish index by 64 records at a time */
47 
48 #define SQUIQSH_IDX_EXPAND    64
49 
50 
51 /* No frame offset */
52 
53 #define NULL_FRAME      ((FOFS)0L)
54 
55 
56 /* Frame types for sqhdr.frame_type */
57 
58 #define FRAME_NORMAL    0x00  /* Normal text frame */
59 #define FRAME_FREE      0x01  /* Part of the free chain */
60 #define FRAME_LZSS      0x02  /* Not implemented */
61 #define FRAME_UPDATE    0x03  /* Frame is being updated by another task */
62 
63 /* BItmask for sqidx.hash to indicate that the msg was received */
64 
65 #define IDXE_MSGREAD    0x80000000Lu
66 
67 /* Macros for accessing the hidden parts of data structures */
68 
69 #define Sqd ((SQDATA *)(ha->apidata))
70 #define HSqd ((SQDATA *)(((struct _msgh *)hmsg)->ha->apidata))
71 
72 
73 /* Squish frame header.  This comes before each and every message in a      *
74  * Squish message base.                                                     */
75 
76 struct _sqhdr
77 {
78   #define SQHDRID       0xafae4453L
79 
80   dword id;             /* sqhdr.id must always equal SQHDRID */
81 
82   FOFS next_frame;      /* Next frame in the linked list */
83   FOFS prev_frame;      /* Prior frame in the linked list */
84 
85   dword frame_length;   /* Length of this frame */
86   dword msg_length;     /* Length used in this frame by XMSG, ctrl and text */
87   dword clen;           /* Length used in this frame by ctrl info only */
88 
89   word frame_type;      /* Type of frame -- see above FRAME_XXXX */
90   word rsvd;            /* Reserved for future use */
91 };
92 
93 
94 
95 /* An individual index entry in <area>.SQI */
96 
97 struct _sqidx
98 {
99   FOFS ofs;                   /* Offset of the frame relating to this msg */
100   UMSGID umsgid;              /* Unique message identifier of this msg */
101   dword hash;                 /* SquishHash of msg.to for this msg */
102 };
103 
104 
105 /* Header block at offset 0 of <area>.SQD */
106 
107 typedef struct _sqbase
108 {
109   word len;               /* LENGTH OF THIS STRUCTURE! */           /*   0 */
110   word rsvd1;             /* reserved */                            /*   2 */
111 
112   dword num_msg;          /* Number of messages in area */          /*   4 */
113   dword high_msg;         /* Highest msg in area. Same as num_msg*/ /*   8 */
114   dword skip_msg;         /* Skip killing first x msgs in area */   /*  12 */
115   dword high_water;       /* Msg# (not umsgid) of HWM */            /*  16 */
116 
117   dword uid;              /* Number of the next UMSGID to use */    /*  20 */
118 
119   byte base[80];          /* Base name of SquishFile */             /*  24 */
120 
121   FOFS begin_frame;       /* Offset of first frame in file */       /* 104 */
122   FOFS last_frame;        /* Offset to last frame in file */        /* 108 */
123   FOFS free_frame;        /* Offset of first FREE frame in file */  /* 112 */
124   FOFS last_free_frame;   /* Offset of last free frame in file */   /* 116 */
125   FOFS end_frame;         /* Pointer to end of file */              /* 120 */
126 
127   dword max_msg;          /* Max # of msgs to keep in area */       /* 124 */
128   word keep_days;         /* Max age of msgs in area (SQPack) */    /* 128 */
129   word sz_sqhdr;          /* sizeof(SQHDR) */                       /* 130 */
130   byte rsvd2[124];        /* Reserved by Squish for future use*/    /* 132 */
131                                                              /* total: 256 */
132 } SQBASE;
133 
134 
135 typedef struct
136 {
137   dword dwUsed;             /* Number of entries used in this seg */
138   dword dwMax;              /* Number of entries allocated in this seg */
139 
140   SQIDX far *psqi;          /* Pointer to index entries for this segment */
141 } SQIDXSEG;
142 
143 
144 /* Handle to a Squish index file */
145 
146 typedef struct
147 {
148   #define ID_HIDX 0x9fee
149 
150   word id;                            /* Must be ID_HIDX */
151   HAREA ha;                           /* Area to which this index belongs */
152 
153   long lAllocatedRecords;             /* Space allocated in idx file */
154   long lDeltaLo;                      /* Low # of changed msg */
155   long lDeltaHi;                      /* High # of changed msg */
156 
157   int fBuffer;                        /* Use index buffer? */
158   int cSeg;                           /* Number of segments used */
159   SQIDXSEG *pss;                      /* Segments containing messages */
160 } *HIDX;
161 
162 
163 
164 /* Private data in handle passed among API functions which handle message   *
165  * areas.                                                                   */
166 
167 typedef struct _sqdata
168 {
169   word cbSqbase;          /* Length of the .SQD file header */
170   word cbSqhdr;           /* Length of a .SQD frame header */
171 
172   dword dwMaxMsg;         /* Max number of msgs in area */
173   word wMaxDays;          /* Max age (in days) of msgs in area */
174   word wSkipMsg;          /* Number of msgs to skip before keeping wMaxMsg */
175 
176   dword dwHighWater;      /* High water message NUMBER */
177   UMSGID uidNext;         /* Next UMSGID to assign */
178 
179   FOFS foFirst;           /* Offset of first frame in file */
180   FOFS foLast;            /* Offset to last frame in file */
181   FOFS foFree;            /* Offset of first FREE frame in file */
182   FOFS foLastFree;        /* Offset of last free frame in file */
183   FOFS foEnd;             /* Pointer to end of file */
184 
185   FOFS foNext;            /* Next frame in the linked list */
186   FOFS foPrev;            /* Prior frame in the linked list */
187   FOFS foCur;             /* Current frame position */
188 
189   word fHaveExclusive;    /* Are we currently updating the base header? */
190   word fLocked;           /* Do we have byte 0 locked? */
191   word fLockFunc;         /* Number of times we have called Lock w/o Unlock */
192 
193   int sfd;                /* SquishFile handle */
194   int ifd;                /* SquishIndex handle */
195 
196   SQBASE sqbDelta;        /* Last _sqbase read from .SQD file */
197 
198   /* Linked lists indicating open resources */
199 
200   HAREA haNext;           /* Next area in the list of open areas */
201   HMSG hmsgOpen;          /* List of open messages */
202   HIDX hix;               /* Index handle for current base */
203 } SQDATA;
204 
205 
206 /* Message handle.  This is passed back and forth between all of the        *
207  * API functions that handle specific messages.                             */
208 
209 struct _msgh
210 {
211   HAREA ha;                   /* Area to which this message belongs */
212   dword id;                   /* Must always equal MSGH_ID */
213 
214   dword bytes_written;        /* Bytes written to this msg so far */
215   dword cur_pos;              /* Current read posn within msg */
216 
217   /* Squish-specific information starts here */
218 
219   dword dwMsg;                /* This message number */
220 
221   /* Frame offset of this message, IF we are reading a message.             *
222    *                                                                        *
223    * However, if we are writing a message, this may hold one of             *
224    * several things, depending on the value of wMode:                       *
225    *                                                                        *
226    *                                                                        *
227    * wMode==MOPEN_CREATE:  If we are writing a completely new message,      *
228    *                       this field is zero.  Otherwise, if we are        *
229    *                       creating a message on top of an existing         *
230    *                       message, this will hold the frame offset of      *
231    *                       the old message.                                 *
232    * wMode==MOPEN_RW       This holds the offset of the message that        *
233    *    or  MOPEN_WRITE    we are rewriting (same as foWrite)               */
234 
235   FOFS foRead;
236 
237   /* SQHDR used when reading.                                               *
238    *                                                                        *
239    * If writing, this will hold the frame header of the message that we     *
240    * replaced.  (We only replaced a message if foRead != NULL_FRAME)        */
241 
242   SQHDR sqhRead;
243 
244   /* If we are writing a message, this holds the offset of the current      *
245    * frame header.  If no frame header has been allocated for the message   *
246    * yet, this field will be NULL_FRAME.                                    */
247 
248   FOFS foWrite;
249 
250   /* If we are writing a message, this holds the frame that we wrote.  This *
251    * SQHDR is only valid when foWrite != NULL_FRAME.                        */
252 
253   SQHDR sqhWrite;
254 
255   /* If we know the UMSGID for this message, uidUs is non-zero */
256 
257   UMSGID uidUs;
258 
259   dword dwWritePos;           /* Current write position */
260   word wMode;                 /* MOPEN_READ, MOPEN_WRITE, or MOPEN_RW */
261   word fDiskErr;              /* Has a disk error occurred? */
262   word fWritten;              /* Have we already written to this message? */
263   HMSG hmsgNext;              /* Next msg in the list of open msgs */
264 };
265 
266 #define SQHDR_SIZE  28
267 #define SQIDX_SIZE  12
268 #define SQBASE_SIZE 256
269 
270 
271 HUSKYEXT int read_xmsg(int handle, XMSG *pxmsg);
272 HUSKYEXT int write_xmsg(int handle, XMSG *pxmsg);
273 HUSKYEXT int read_sqhdr(int, SQHDR *);
274 HUSKYEXT int write_sqhdr(int, SQHDR *);
275 HUSKYEXT int read_sqidx(int, SQIDX *, dword);
276 HUSKYEXT int write_sqidx(int, SQIDX *, dword);
277 HUSKYEXT int read_sqbase(int handle, struct _sqbase *psqbase);
278 HUSKYEXT int write_sqbase(int handle, struct _sqbase *psqbase);
279 
280 #endif /* __API_SQ_H_DEFINED */
281 
282