1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20: #include <byteswap.h>
21: #include <endian.h>
22: #include <errno.h>
23: #include <fcntl.h>
24: #include <string.h>
25: #include <stdlib.h>
26: #include <unistd.h>
27: #ifdef _POSIX_MAPPED_FILES
28: # include <sys/mman.h>
29: #endif
30: #include <sys/stat.h>
31:
32: #include "catgetsinfo.h"
33: #include <not-cancel.h>
34:
35:
36: #define SWAPU32(w) bswap_32 (w)
37:
38:
39: int
40: __open_catalog (const char *cat_name, const char *nlspath, const char *env_var,
41: __nl_catd catalog)
42: {
43: int fd = -1;
44: struct stat64 st;
45: int swapping;
46: size_t cnt;
47: size_t max_offset;
48: size_t tab_size;
49: const char *lastp;
50: int result = -1;
51:
52: if (strchr (cat_name, '/') != NULL || nlspath == NULL)
53: fd = open_not_cancel_2 (cat_name, O_RDONLY);
54: else
55: {
56: const char *run_nlspath = nlspath;
57: #define ENOUGH(n) \
58: if (__builtin_expect (bufact + (n) >= bufmax, 0)) \
59: { \
60: char *old_buf = buf; \
61: bufmax += 256 + (n); \
62: buf = (char *) alloca (bufmax); \
63: memcpy (buf, old_buf, bufact); \
64: }
65:
66:
67:
68:
69:
70: char *buf;
71: size_t bufact;
72: size_t bufmax;
73: size_t len;
74:
75: buf = NULL;
76: bufmax = 0;
77:
78: fd = -1;
79: while (*run_nlspath != '\0')
80: {
81: bufact = 0;
82:
83: if (*run_nlspath == ':')
84: {
85:
86: len = strlen (cat_name);
87: ENOUGH (len);
88: memcpy (&buf[bufact], cat_name, len);
89: bufact += len;
90: }
91: else
92: while (*run_nlspath != ':' && *run_nlspath != '\0')
93: if (*run_nlspath == '%')
94: {
95: const char *tmp;
96:
97: ++run_nlspath;
98: switch (*run_nlspath++)
99: {
100: case 'N':
101:
102: len = strlen (cat_name);
103: ENOUGH (len);
104: memcpy (&buf[bufact], cat_name, len);
105: bufact += len;
106: break;
107: case 'L':
108:
109: len = strlen (env_var);
110: ENOUGH (len);
111: memcpy (&buf[bufact], env_var, len);
112: bufact += len;
113: break;
114: case 'l':
115:
116: tmp = env_var;
117: do
118: {
119: ENOUGH (1);
120: buf[bufact++] = *tmp++;
121: }
122: while (*tmp != '\0' && *tmp != '_' && *tmp != '.');
123: break;
124: case 't':
125:
126: tmp = env_var;
127: do
128: ++tmp;
129: while (*tmp != '\0' && *tmp != '_' && *tmp != '.');
130: if (*tmp == '_')
131: {
132: ++tmp;
133: do
134: {
135: ENOUGH (1);
136: buf[bufact++] = *tmp++;
137: }
138: while (*tmp != '\0' && *tmp != '.');
139: }
140: break;
141: case 'c':
142:
143: tmp = env_var;
144: do
145: ++tmp;
146: while (*tmp != '\0' && *tmp != '.');
147: if (*tmp == '.')
148: {
149: ++tmp;
150: do
151: {
152: ENOUGH (1);
153: buf[bufact++] = *tmp++;
154: }
155: while (*tmp != '\0');
156: }
157: break;
158: case '%':
159: ENOUGH (1);
160: buf[bufact++] = '%';
161: break;
162: default:
163:
164: bufact = 0;
165: while (*run_nlspath != '\0' && *run_nlspath != ':')
166: ++run_nlspath;
167: break;
168: }
169: }
170: else
171: {
172: ENOUGH (1);
173: buf[bufact++] = *run_nlspath++;
174: }
175:
176: ENOUGH (1);
177: buf[bufact] = '\0';
178:
179: if (bufact != 0)
180: {
181: fd = open_not_cancel_2 (buf, O_RDONLY);
182: if (fd >= 0)
183: break;
184: }
185:
186: ++run_nlspath;
187: }
188: }
189:
190:
191: if (__builtin_expect (fd, 0) < 0)
192: return -1;
193:
194: if (__builtin_expect (__fxstat64 (_STAT_VER, fd, &st), 0) < 0)
195: goto close_unlock_return;
196:
197: if (__builtin_expect (!S_ISREG (st.st_mode), 0)
198: || (size_t) st.st_size < sizeof (struct catalog_obj))
199: {
200:
201:
202: __set_errno (EINVAL);
203: goto close_unlock_return;
204: }
205:
206: catalog->file_size = st.st_size;
207: #ifdef _POSIX_MAPPED_FILES
208: # ifndef MAP_COPY
209:
210: # define MAP_COPY MAP_PRIVATE
211: # endif
212: # ifndef MAP_FILE
213:
214: # define MAP_FILE 0
215: # endif
216: catalog->file_ptr =
217: (struct catalog_obj *) __mmap (NULL, st.st_size, PROT_READ,
218: MAP_FILE|MAP_COPY, fd, 0);
219: if (__builtin_expect (catalog->file_ptr != (struct catalog_obj *) MAP_FAILED,
220: 1))
221:
222: catalog->status = mmapped;
223: else
224: #endif
225: {
226:
227:
228: size_t todo;
229: catalog->file_ptr = malloc (st.st_size);
230: if (catalog->file_ptr == NULL)
231: goto close_unlock_return;
232:
233: todo = st.st_size;
234:
235: do
236: {
237: size_t now = read_not_cancel (fd, (((char *) catalog->file_ptr)
238: + (st.st_size - todo)), todo);
239: if (now == 0 || now == (size_t) -1)
240: {
241: #ifdef EINTR
242: if (now == (size_t) -1 && errno == EINTR)
243: continue;
244: #endif
245: free ((void *) catalog->file_ptr);
246: goto close_unlock_return;
247: }
248: todo -= now;
249: }
250: while (todo > 0);
251: catalog->status = malloced;
252: }
253:
254:
255:
256:
257: if (__builtin_expect (catalog->file_ptr->magic == CATGETS_MAGIC, 1))
258: swapping = 0;
259: else if (catalog->file_ptr->magic == SWAPU32 (CATGETS_MAGIC))
260: swapping = 1;
261: else
262: {
263: invalid_file:
264:
265:
266: #ifdef _POSIX_MAPPED_FILES
267: if (catalog->status == mmapped)
268: __munmap ((void *) catalog->file_ptr, catalog->file_size);
269: else
270: #endif
271: free (catalog->file_ptr);
272: goto close_unlock_return;
273: }
274:
275: #define SWAP(x) (swapping ? SWAPU32 (x) : (x))
276:
277:
278: catalog->plane_size = SWAP (catalog->file_ptr->plane_size);
279: catalog->plane_depth = SWAP (catalog->file_ptr->plane_depth);
280:
281:
282:
283: #if __BYTE_ORDER == __LITTLE_ENDIAN
284: catalog->name_ptr = &catalog->file_ptr->name_ptr[0];
285: #elif __BYTE_ORDER == __BIG_ENDIAN
286: catalog->name_ptr = &catalog->file_ptr->name_ptr[catalog->plane_size
287: * catalog->plane_depth
288: * 3];
289: #else
290: # error Cannot handle __BYTE_ORDER byte order
291: #endif
292:
293:
294:
295: catalog->strings =
296: (const char *) &catalog->file_ptr->name_ptr[catalog->plane_size
297: * catalog->plane_depth * 3 * 2];
298:
299:
300: max_offset = 0;
301: tab_size = 3 * catalog->plane_size * catalog->plane_depth;
302: for (cnt = 2; cnt < tab_size; cnt += 3)
303: if (catalog->name_ptr[cnt] > max_offset)
304: max_offset = catalog->name_ptr[cnt];
305:
306:
307:
308: if ((size_t) st.st_size
309: <= (sizeof (struct catalog_obj) + 2 * tab_size + max_offset))
310:
311: goto invalid_file;
312:
313: lastp = catalog->strings + max_offset;
314: max_offset = (st.st_size
315: - sizeof (struct catalog_obj) + 2 * tab_size + max_offset);
316: while (*lastp != '\0')
317: {
318: if (--max_offset == 0)
319: goto invalid_file;
320: ++lastp;
321: }
322:
323:
324: result = 0;
325:
326:
327: close_unlock_return:
328: close_not_cancel_no_status (fd);
329:
330: return result;
331: }
332: libc_hidden_def (__open_catalog)