msgcat.c (29c271590ecdfcb3e424ca1b98ad814210ea7af2) msgcat.c (6eaef61813d1dd6a09aee3191005770859733893)
1/* $Id$ */
2
1/***********************************************************
2Copyright 1990, by Alfalfa Software Incorporated, Cambridge, Massachusetts.
3/***********************************************************
4Copyright 1990, by Alfalfa Software Incorporated, Cambridge, Massachusetts.
3Copyright 2010, Gabor Kovesdan <gabor@FreeBSD.org>
4
5 All Rights Reserved
6
7Permission to use, copy, modify, and distribute this software and its
8documentation for any purpose and without fee is hereby granted,
9provided that the above copyright notice appear in all copies and that
10both that copyright notice and this permission notice appear in
11supporting documentation, and that Alfalfa's name not be used in

--- 11 unchanged lines hidden (view full) ---

23If you make any modifications, bugfixes or other changes to this software
24we'd appreciate it if you could send a copy to us so we can keep things
25up-to-date. Many thanks.
26 Kee Hinckley
27 Alfalfa Software, Inc.
28 267 Allston St., #3
29 Cambridge, MA 02139 USA
30 nazgul@alfalfa.com
5
6 All Rights Reserved
7
8Permission to use, copy, modify, and distribute this software and its
9documentation for any purpose and without fee is hereby granted,
10provided that the above copyright notice appear in all copies and that
11both that copyright notice and this permission notice appear in
12supporting documentation, and that Alfalfa's name not be used in

--- 11 unchanged lines hidden (view full) ---

24If you make any modifications, bugfixes or other changes to this software
25we'd appreciate it if you could send a copy to us so we can keep things
26up-to-date. Many thanks.
27 Kee Hinckley
28 Alfalfa Software, Inc.
29 267 Allston St., #3
30 Cambridge, MA 02139 USA
31 nazgul@alfalfa.com
31
32
32******************************************************************/
33
33******************************************************************/
34
34#include <sys/cdefs.h>
35__FBSDID("$FreeBSD$");
35#if defined(LIBC_SCCS) && !defined(lint)
36static char *rcsid = "$NetBSD: msgcat.c,v 1.11 1995/02/27 13:06:51 cgd Exp $";
37#endif /* LIBC_SCCS and not lint */
36
38
37#define _NLS_PRIVATE
39/* Edit History
38
40
39#include "namespace.h"
40#include <sys/types.h>
41#include <sys/stat.h>
42#include <sys/mman.h>
43#include <sys/queue.h>
4103/06/91 4 schulert remove working directory from nlspath
4201/18/91 2 hamilton #if not rescanned
4301/12/91 3 schulert conditionally use prototypes
4411/03/90 1 hamilton Alphalpha->Alfalfa & OmegaMail->Poste
4510/15/90 2 schulert > #include <unistd.h> if MIPS
4608/13/90 1 schulert move from ua to omu
47*/
44
48
45#include <arpa/inet.h> /* for ntohl() */
49/*
50 * We need a better way of handling errors than printing text. I need
51 * to add an error handling routine.
52 */
46
53
47#include <errno.h>
54#include "nl_types.h"
55#include "msgcat.h"
56
57#include <sys/types.h>
58#include <sys/stat.h>
48#include <fcntl.h>
59#include <fcntl.h>
49#include <limits.h>
50#include <locale.h>
51#include <nl_types.h>
52#include <pthread.h>
53#include <stdio.h>
54#include <stdlib.h>
55#include <string.h>
56#include <unistd.h>
60#include <stdio.h>
61#include <stdlib.h>
62#include <string.h>
63#include <unistd.h>
57#include "un-namespace.h"
58
64
59#include "../locale/setlocale.h" /* for ENCODING_LEN */
65#ifndef True
66# define True ~0
67# define False 0
68#endif
60
69
61#define _DEFAULT_NLS_PATH "/usr/share/nls/%L/%N.cat:/usr/share/nls/%N/%L:/usr/local/share/nls/%L/%N.cat:/usr/local/share/nls/%N/%L"
70/* take care of sysv diffs */
71#ifndef MAXPATHLEN
72#define MAXPATHLEN 1024
73#endif
62
74
63#define RLOCK(fail) { int ret; \
64 if (__isthreaded && \
65 ((ret = _pthread_rwlock_rdlock(&rwlock)) != 0)) { \
66 errno = ret; \
67 return (fail); \
68 }}
69#define WLOCK(fail) { int ret; \
70 if (__isthreaded && \
71 ((ret = _pthread_rwlock_wrlock(&rwlock)) != 0)) { \
72 errno = ret; \
73 return (fail); \
74 }}
75#define UNLOCK { if (__isthreaded) \
76 _pthread_rwlock_unlock(&rwlock); }
75#ifndef FD_CLOEXEC
76#define FD_CLOEXEC 1
77#endif
77
78
78#define NLERR ((nl_catd) -1)
79#define NLRETERR(errc) { errno = errc; return (NLERR); }
80#define SAVEFAIL(n, l, e) { WLOCK(NLERR); \
81 np = malloc(sizeof(struct catentry)); \
82 if (np != NULL) { \
83 np->name = strdup(n); \
84 np->path = NULL; \
85 np->lang = (l == NULL) ? NULL : \
86 strdup(l); \
87 np->caterrno = e; \
88 SLIST_INSERT_HEAD(&cache, np, list); \
89 } \
90 UNLOCK; \
91 errno = e; \
92 }
79#define NLERR ((nl_catd) -1)
93
80
94static nl_catd load_msgcat(const char *, const char *, const char *);
81static nl_catd loadCat();
82static nl_catd loadSet();
95
83
96static pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER;
97
98struct catentry {
99 SLIST_ENTRY(catentry) list;
100 char *name;
101 char *path;
102 int caterrno;
103 nl_catd catd;
104 char *lang;
105 int refcount;
106};
107
108SLIST_HEAD(listhead, catentry) cache =
109 SLIST_HEAD_INITIALIZER(cache);
110
111nl_catd
112catopen(const char *name, int type)
84nl_catd _catopen( name, type)
85__const char *name;
86int type;
113{
87{
114 struct stat sbuf;
115 struct catentry *np;
116 char *base, *cptr, *cptr1, *lang, *nlspath, *pathP, *pcode;
117 char *plang, *pter, *tmpptr;
118 int saverr, spcleft;
119 char path[PATH_MAX];
88 char path[MAXPATHLEN];
89 __const char *catpath = NULL;
90 char *nlspath, *tmppath = NULL;
91 char *lang;
92 long len;
93 char *base, *cptr, *pathP;
94 struct stat sbuf;
95
96 if (!name || !*name) return(NLERR);
120
97
121 /* sanity checking */
122 if (name == NULL || *name == '\0')
123 NLRETERR(EINVAL);
124
125 if (strchr(name, '/') != NULL)
126 /* have a pathname */
127 lang = NULL;
128 else {
129 if (type == NL_CAT_LOCALE)
130 lang = setlocale(LC_MESSAGES, NULL);
131 else
132 lang = getenv("LANG");
133
134 if (lang == NULL || *lang == '\0' || strlen(lang) > ENCODING_LEN ||
135 (lang[0] == '.' &&
136 (lang[1] == '\0' || (lang[1] == '.' && lang[2] == '\0'))) ||
137 strchr(lang, '/') != NULL)
138 lang = "C";
98 if (strchr(name, '/')) {
99 catpath = name;
100 if (stat(catpath, &sbuf)) return(0);
101 } else {
102 if ((lang = (char *) getenv("LANG")) == NULL) lang = "C";
103 if ((nlspath = (char *) getenv("NLSPATH")) == NULL) {
104 nlspath = "/usr/share/nls/%L/%N.cat:/usr/share/nls/%N/%L";
139 }
105 }
140
141 /* Try to get it from the cache first */
142 RLOCK(NLERR);
143 SLIST_FOREACH(np, &cache, list) {
144 if ((strcmp(np->name, name) == 0) &&
145 ((lang != NULL && np->lang != NULL &&
146 strcmp(np->lang, lang) == 0) || (np->lang == lang))) {
147 if (np->caterrno != 0) {
148 /* Found cached failing entry */
149 UNLOCK;
150 NLRETERR(np->caterrno);
151 } else {
152 /* Found cached successful entry */
153 np->refcount++;
154 UNLOCK;
155 return (np->catd);
156 }
106
107 len = strlen(nlspath);
108 base = cptr = (char *) malloc(len + 2);
109 if (!base) return(NLERR);
110 strcpy(cptr, nlspath);
111 cptr[len] = ':';
112 cptr[len+1] = '\0';
113
114 for (nlspath = cptr; *cptr; ++cptr) {
115 if (*cptr == ':') {
116 *cptr = '\0';
117 for (pathP = path; *nlspath; ++nlspath) {
118 if (*nlspath == '%') {
119 if (*(nlspath + 1) == 'L') {
120 ++nlspath;
121 strcpy(pathP, lang);
122 pathP += strlen(lang);
123 } else if (*(nlspath + 1) == 'N') {
124 ++nlspath;
125 strcpy(pathP, name);
126 pathP += strlen(name);
127 } else *(pathP++) = *nlspath;
128 } else *(pathP++) = *nlspath;
157 }
129 }
130 *pathP = '\0';
131 if (stat(path, &sbuf) == 0) {
132 catpath = path;
133 break;
134 }
135 nlspath = cptr+1;
136 }
158 }
137 }
159 UNLOCK;
138 free(base);
139 if (tmppath) free(tmppath);
160
140
161 /* is it absolute path ? if yes, load immediately */
162 if (strchr(name, '/') != NULL)
163 return (load_msgcat(name, name, lang));
141 if (!catpath) return(0);
142 }
164
143
165 /* sanity checking */
166 if ((plang = cptr1 = strdup(lang)) == NULL)
167 return (NLERR);
168 if ((cptr = strchr(cptr1, '@')) != NULL)
169 *cptr = '\0';
170 pter = pcode = "";
171 if ((cptr = strchr(cptr1, '_')) != NULL) {
172 *cptr++ = '\0';
173 pter = cptr1 = cptr;
174 }
175 if ((cptr = strchr(cptr1, '.')) != NULL) {
176 *cptr++ = '\0';
177 pcode = cptr;
178 }
144 return(loadCat(catpath, type));
145}
179
146
180 if ((nlspath = getenv("NLSPATH")) == NULL || issetugid())
181 nlspath = _DEFAULT_NLS_PATH;
147/*
148 * We've got an odd situation here. The odds are real good that the
149 * number we are looking for is almost the same as the index. We could
150 * use the index, check the difference and do something intelligent, but
151 * I haven't quite figured out what's intelligent.
152 *
153 * Here's a start.
154 * Take an id N. If there are > N items in the list, then N cannot
155 * be more than N items from the start, since otherwise there would
156 * have to be duplicate items. So we can safely set the top to N+1
157 * (after taking into account that ids start at 1, and arrays at 0)
158 *
159 * Let's say we are at position P, and we are looking for N, but have
160 * V. If N > V, then the furthest away that N could be is
161 * P + (N-V). So we can safely set hi to P+(N-V)+1. For example:
162 * We are looking for 10, but have 8
163 * 8 ? ? ? ?
164 * >=9 >=10 >=11
165 *
166 */
167static MCSetT *MCGetSet( cat, setId)
168MCCatT *cat;
169int setId;
170{
171 MCSetT *set;
172 long lo, hi, cur, dir;
182
173
183 if ((base = cptr = strdup(nlspath)) == NULL) {
184 saverr = errno;
185 free(plang);
186 errno = saverr;
187 return (NLERR);
188 }
174 if (!cat || setId <= 0) return(NULL);
189
175
190 while ((nlspath = strsep(&cptr, ":")) != NULL) {
191 pathP = path;
192 if (*nlspath) {
193 for (; *nlspath; ++nlspath) {
194 if (*nlspath == '%') {
195 switch (*(nlspath + 1)) {
196 case 'l':
197 tmpptr = plang;
198 break;
199 case 't':
200 tmpptr = pter;
201 break;
202 case 'c':
203 tmpptr = pcode;
204 break;
205 case 'L':
206 tmpptr = lang;
207 break;
208 case 'N':
209 tmpptr = (char *)name;
210 break;
211 case '%':
212 ++nlspath;
213 /* FALLTHROUGH */
214 default:
215 if (pathP - path >=
216 sizeof(path) - 1)
217 goto too_long;
218 *(pathP++) = *nlspath;
219 continue;
220 }
221 ++nlspath;
222 put_tmpptr:
223 spcleft = sizeof(path) -
224 (pathP - path) - 1;
225 if (strlcpy(pathP, tmpptr, spcleft) >=
226 spcleft) {
227 too_long:
228 free(plang);
229 free(base);
230 SAVEFAIL(name, lang, ENAMETOOLONG);
231 NLRETERR(ENAMETOOLONG);
232 }
233 pathP += strlen(tmpptr);
234 } else {
235 if (pathP - path >= sizeof(path) - 1)
236 goto too_long;
237 *(pathP++) = *nlspath;
238 }
239 }
240 *pathP = '\0';
241 if (stat(path, &sbuf) == 0) {
242 free(plang);
243 free(base);
244 return (load_msgcat(path, name, lang));
245 }
246 } else {
247 tmpptr = (char *)name;
248 --nlspath;
249 goto put_tmpptr;
250 }
176 lo = 0;
177 if (setId - 1 < cat->numSets) {
178 cur = setId - 1;
179 hi = setId;
180 } else {
181 hi = cat->numSets;
182 cur = (hi - lo) / 2;
183 }
184
185 while (True) {
186 set = cat->sets + cur;
187 if (set->setId == setId) break;
188 if (set->setId < setId) {
189 lo = cur+1;
190 if (hi > cur + (setId - set->setId) + 1) hi = cur+(setId-set->setId)+1;
191 dir = 1;
192 } else {
193 hi = cur;
194 dir = -1;
251 }
195 }
252 free(plang);
253 free(base);
254 SAVEFAIL(name, lang, ENOENT);
255 NLRETERR(ENOENT);
196 if (lo >= hi) return(NULL);
197 if (hi - lo == 1) cur += dir;
198 else cur += ((hi - lo) / 2) * dir;
199 }
200 if (set->invalid) loadSet(cat, set);
201 return(set);
256}
257
202}
203
258char *
259catgets(nl_catd catd, int set_id, int msg_id, const char *s)
204
205static MCMsgT *MCGetMsg( set, msgId)
206MCSetT *set;
207int msgId;
260{
208{
261 struct _nls_cat_hdr *cat_hdr;
262 struct _nls_msg_hdr *msg_hdr;
263 struct _nls_set_hdr *set_hdr;
264 int i, l, r, u;
265
266 if (catd == NULL || catd == NLERR) {
267 errno = EBADF;
268 /* LINTED interface problem */
269 return ((char *)s);
209 MCMsgT *msg;
210 long lo, hi, cur, dir;
211
212 if (!set || set->invalid || msgId <= 0) return(NULL);
213
214 lo = 0;
215 if (msgId - 1 < set->numMsgs) {
216 cur = msgId - 1;
217 hi = msgId;
218 } else {
219 hi = set->numMsgs;
220 cur = (hi - lo) / 2;
221 }
222
223 while (True) {
224 msg = set->u.msgs + cur;
225 if (msg->msgId == msgId) break;
226 if (msg->msgId < msgId) {
227 lo = cur+1;
228 if (hi > cur + (msgId - msg->msgId) + 1) hi = cur+(msgId-msg->msgId)+1;
229 dir = 1;
230 } else {
231 hi = cur;
232 dir = -1;
270 }
233 }
234 if (lo >= hi) return(NULL);
235 if (hi - lo == 1) cur += dir;
236 else cur += ((hi - lo) / 2) * dir;
237 }
238 return(msg);
239}
271
240
272 cat_hdr = (struct _nls_cat_hdr *)catd->__data;
273 set_hdr = (struct _nls_set_hdr *)(void *)((char *)catd->__data +
274 sizeof(struct _nls_cat_hdr));
241char *_catgets( catd, setId, msgId, dflt)
242nl_catd catd;
243int setId;
244int msgId;
245char *dflt;
246{
247 MCMsgT *msg;
248 MCCatT *cat = (MCCatT *) catd;
249 char *cptr;
275
250
276 /* binary search, see knuth algorithm b */
277 l = 0;
278 u = ntohl((u_int32_t)cat_hdr->__nsets) - 1;
279 while (l <= u) {
280 i = (l + u) / 2;
281 r = set_id - ntohl((u_int32_t)set_hdr[i].__setno);
282
283 if (r == 0) {
284 msg_hdr = (struct _nls_msg_hdr *)
285 (void *)((char *)catd->__data +
286 sizeof(struct _nls_cat_hdr) +
287 ntohl((u_int32_t)cat_hdr->__msg_hdr_offset));
288
289 l = ntohl((u_int32_t)set_hdr[i].__index);
290 u = l + ntohl((u_int32_t)set_hdr[i].__nmsgs) - 1;
291 while (l <= u) {
292 i = (l + u) / 2;
293 r = msg_id -
294 ntohl((u_int32_t)msg_hdr[i].__msgno);
295 if (r == 0) {
296 return ((char *) catd->__data +
297 sizeof(struct _nls_cat_hdr) +
298 ntohl((u_int32_t)
299 cat_hdr->__msg_txt_offset) +
300 ntohl((u_int32_t)
301 msg_hdr[i].__offset));
302 } else if (r < 0) {
303 u = i - 1;
304 } else {
305 l = i + 1;
306 }
307 }
308
309 /* not found */
310 goto notfound;
311
312 } else if (r < 0) {
313 u = i - 1;
314 } else {
315 l = i + 1;
316 }
317 }
318
319notfound:
320 /* not found */
321 errno = ENOMSG;
322 /* LINTED interface problem */
323 return ((char *)s);
251 msg = MCGetMsg(MCGetSet(cat, setId), msgId);
252 if (msg) cptr = msg->msg.str;
253 else cptr = dflt;
254 return(cptr);
324}
325
255}
256
326int
327catclose(nl_catd catd)
257
258int _catclose( catd)
259nl_catd catd;
328{
260{
329 struct catentry *np;
261 MCCatT *cat = (MCCatT *) catd;
262 MCSetT *set;
263 MCMsgT *msg;
264 int i, j;
330
265
331 /* sanity checking */
332 if (catd == NULL || catd == NLERR) {
333 errno = EBADF;
334 return (-1);
266 if (!cat) return -1;
267
268 if (cat->loadType != MCLoadAll) close(cat->fd);
269 for (i = 0; i < cat->numSets; ++i) {
270 set = cat->sets + i;
271 if (!set->invalid) {
272 free(set->data.str);
273 free(set->u.msgs);
335 }
274 }
275 }
276 free(cat->sets);
277 free(cat);
336
278
337 /* Remove from cache if not referenced any more */
338 WLOCK(-1);
339 SLIST_FOREACH(np, &cache, list) {
340 if (catd == np->catd) {
341 np->refcount--;
342 if (np->refcount == 0) {
343 munmap(catd->__data, (size_t)catd->__size);
344 free(catd);
345 SLIST_REMOVE(&cache, np, catentry, list);
346 free(np->name);
347 free(np->path);
348 free(np->lang);
349 free(np);
350 }
351 break;
352 }
353 }
354 UNLOCK;
355 return (0);
279 return 0;
356}
357
358/*
280}
281
282/*
359 * Internal support functions
283 * Internal routines
360 */
361
284 */
285
362static nl_catd
363load_msgcat(const char *path, const char *name, const char *lang)
286/* Note that only malloc failures are allowed to return an error */
287#define ERRNAME "Message Catalog System"
288#define CORRUPT() {fprintf(stderr, "%s: corrupt file.\n", ERRNAME); return(0);}
289#define NOSPACE() {fprintf(stderr, "%s: no more memory.\n", ERRNAME); return(NLERR);}
290
291static nl_catd loadCat( catpath, type)
292__const char *catpath;
293int type;
364{
294{
365 struct stat st;
366 nl_catd catd;
367 struct catentry *np;
368 void *data;
369 int fd;
295 MCHeaderT header;
296 MCCatT *cat;
297 MCSetT *set;
298 MCMsgT *msg;
299 long i, j;
300 off_t nextSet;
370
301
371 /* path/name will never be NULL here */
302 cat = (MCCatT *) malloc(sizeof(MCCatT));
303 if (!cat) return(NLERR);
304 cat->loadType = type;
372
305
373 /*
374 * One more try in cache; if it was not found by name,
375 * it might still be found by absolute path.
376 */
377 RLOCK(NLERR);
378 SLIST_FOREACH(np, &cache, list) {
379 if ((np->path != NULL) && (strcmp(np->path, path) == 0)) {
380 np->refcount++;
381 UNLOCK;
382 return (np->catd);
383 }
384 }
385 UNLOCK;
306 if ((cat->fd = open(catpath, O_RDONLY)) < 0) {
307 return(0);
308 }
386
309
387 if ((fd = _open(path, O_RDONLY)) == -1) {
388 SAVEFAIL(name, lang, errno);
389 NLRETERR(errno);
390 }
310 fcntl(cat->fd, F_SETFD, FD_CLOEXEC);
391
311
392 if (_fstat(fd, &st) != 0) {
393 _close(fd);
394 SAVEFAIL(name, lang, EFTYPE);
395 NLRETERR(EFTYPE);
396 }
312 if (read(cat->fd, &header, sizeof(header)) != sizeof(header)) CORRUPT();
397
313
398 /*
399 * If the file size cannot be held in size_t we cannot mmap()
400 * it to the memory. Probably, this will not be a problem given
401 * that catalog files are usually small.
402 */
403 if (st.st_size > SIZE_T_MAX) {
404 _close(fd);
405 SAVEFAIL(name, lang, EFBIG);
406 NLRETERR(EFBIG);
407 }
314 if (strncmp(header.magic, MCMagic, MCMagicLen) != 0) CORRUPT();
315
316 if (header.majorVer != MCMajorVer) {
317 fprintf(stderr, "%s: %s is version %d, we need %d.\n", ERRNAME,
318 catpath, header.majorVer, MCMajorVer);
319 return(0);
320 }
321
322 if (header.numSets <= 0) {
323 fprintf(stderr, "%s: %s has %d sets!\n", ERRNAME, catpath,
324 header.numSets);
325 return(0);
326 }
408
327
409 if ((data = mmap(0, (size_t)st.st_size, PROT_READ,
410 MAP_FILE|MAP_SHARED, fd, (off_t)0)) == MAP_FAILED) {
411 int saved_errno = errno;
412 _close(fd);
413 SAVEFAIL(name, lang, saved_errno);
414 NLRETERR(saved_errno);
415 }
416 _close(fd);
328 cat->numSets = header.numSets;
329 cat->sets = (MCSetT *) malloc(sizeof(MCSetT) * header.numSets);
330 if (!cat->sets) NOSPACE();
417
331
418 if (ntohl((u_int32_t)((struct _nls_cat_hdr *)data)->__magic) !=
419 _NLS_MAGIC) {
420 munmap(data, (size_t)st.st_size);
421 SAVEFAIL(name, lang, EFTYPE);
422 NLRETERR(EFTYPE);
423 }
332 nextSet = header.firstSet;
333 for (i = 0; i < cat->numSets; ++i) {
334 if (lseek(cat->fd, nextSet, 0) == -1) CORRUPT();
424
335
425 if ((catd = malloc(sizeof (*catd))) == NULL) {
426 munmap(data, (size_t)st.st_size);
427 SAVEFAIL(name, lang, ENOMEM);
428 NLRETERR(ENOMEM);
336 /* read in the set header */
337 set = cat->sets + i;
338 if (read(cat->fd, set, sizeof(*set)) != sizeof(*set)) CORRUPT();
339
340 /* if it's invalid, skip over it (and backup 'i') */
341
342 if (set->invalid) {
343 --i;
344 nextSet = set->nextSet;
345 continue;
429 }
430
346 }
347
431 catd->__data = data;
432 catd->__size = (int)st.st_size;
348 if (cat->loadType == MCLoadAll) {
349 nl_catd res;
350 if ((res = loadSet(cat, set)) <= 0) {
351 if (res == -1) NOSPACE();
352 CORRUPT();
353 }
354 } else set->invalid = True;
355 nextSet = set->nextSet;
356 }
357 if (cat->loadType == MCLoadAll) {
358 close(cat->fd);
359 cat->fd = -1;
360 }
361 return((nl_catd) cat);
362}
433
363
434 /* Caching opened catalog */
435 WLOCK(NLERR);
436 if ((np = malloc(sizeof(struct catentry))) != NULL) {
437 np->name = strdup(name);
438 np->path = strdup(path);
439 np->catd = catd;
440 np->lang = (lang == NULL) ? NULL : strdup(lang);
441 np->refcount = 1;
442 np->caterrno = 0;
443 SLIST_INSERT_HEAD(&cache, np, list);
364static nl_catd loadSet( cat, set)
365MCCatT *cat;
366MCSetT *set;
367{
368 MCMsgT *msg;
369 int i;
370
371 /* Get the data */
372 if (lseek(cat->fd, set->data.off, 0) == -1) return(0);
373 if ((set->data.str = (char *) malloc(set->dataLen)) == NULL) return(-1);
374 if (read(cat->fd, set->data.str, set->dataLen) != set->dataLen) return(0);
375
376 /* Get the messages */
377 if (lseek(cat->fd, set->u.firstMsg, 0) == -1) return(0);
378 if ((set->u.msgs = (MCMsgT *) malloc(sizeof(MCMsgT) * set->numMsgs)) == NULL) return(-1);
379
380 for (i = 0; i < set->numMsgs; ++i) {
381 msg = set->u.msgs + i;
382 if (read(cat->fd, msg, sizeof(*msg)) != sizeof(*msg)) return(0);
383 if (msg->invalid) {
384 --i;
385 continue;
444 }
386 }
445 UNLOCK;
446 return (catd);
387 msg->msg.str = (char *) (set->data.str + msg->msg.off);
388 }
389 set->invalid = False;
390 return(1);
447}
391}
392
393
394
395
396