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 |
|