OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [newlib-1.17.0/] [newlib/] [libc/] [sys/] [linux/] [intl/] [open_catalog.c] - Blame information for rev 816

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 148 jeremybenn
/* Copyright (C) 1996-2000, 2001, 2002 Free Software Foundation, Inc.
2
   This file is part of the GNU C Library.
3
   Contributed by Ulrich Drepper, <drepper@gnu.org>.
4
 
5
   The GNU C Library is free software; you can redistribute it and/or
6
   modify it under the terms of the GNU Lesser General Public
7
   License as published by the Free Software Foundation; either
8
   version 2.1 of the License, or (at your option) any later version.
9
 
10
   The GNU C Library is distributed in the hope that it will be useful,
11
   but WITHOUT ANY WARRANTY; without even the implied warranty of
12
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13
   Lesser General Public License for more details.
14
 
15
   You should have received a copy of the GNU Lesser General Public
16
   License along with the GNU C Library; if not, write to the Free
17
   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18
   02111-1307 USA.  */
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
 
34
 
35
#define SWAPU32(w) bswap_32 (w)
36
 
37
 
38
int
39
__open_catalog (const char *cat_name, const char *nlspath, const char *env_var,
40
                __nl_catd catalog)
41
{
42
  int fd = -1;
43
  struct stat64 st;
44
  int swapping;
45
  size_t cnt;
46
  size_t max_offset;
47
  size_t tab_size;
48
  const char *lastp;
49
  int result = -1;
50
 
51
  if (strchr (cat_name, '/') != NULL || nlspath == NULL)
52
    fd = __open (cat_name, O_RDONLY);
53
  else
54
    {
55
      const char *run_nlspath = nlspath;
56
#define ENOUGH(n)                                                             \
57
  if (__builtin_expect (bufact + (n) >= bufmax, 0))                            \
58
    {                                                                         \
59
      char *old_buf = buf;                                                    \
60
      bufmax += 256 + (n);                                                    \
61
      buf = (char *) alloca (bufmax);                                         \
62
      memcpy (buf, old_buf, bufact);                                          \
63
    }
64
 
65
      /* The RUN_NLSPATH variable contains a colon separated list of
66
         descriptions where we expect to find catalogs.  We have to
67
         recognize certain % substitutions and stop when we found the
68
         first existing file.  */
69
      char *buf;
70
      size_t bufact;
71
      size_t bufmax;
72
      size_t len;
73
 
74
      buf = NULL;
75
      bufmax = 0;
76
 
77
      fd = -1;
78
      while (*run_nlspath != '\0')
79
        {
80
          bufact = 0;
81
 
82
          if (*run_nlspath == ':')
83
            {
84
              /* Leading colon or adjacent colons - treat same as %N.  */
85
              len = strlen (cat_name);
86
              ENOUGH (len);
87
              memcpy (&buf[bufact], cat_name, len);
88
              bufact += len;
89
            }
90
          else
91
            while (*run_nlspath != ':' && *run_nlspath != '\0')
92
              if (*run_nlspath == '%')
93
                {
94
                  const char *tmp;
95
 
96
                  ++run_nlspath;        /* We have seen the `%'.  */
97
                  switch (*run_nlspath++)
98
                    {
99
                    case 'N':
100
                      /* Use the catalog name.  */
101
                      len = strlen (cat_name);
102
                      ENOUGH (len);
103
                      memcpy (&buf[bufact], cat_name, len);
104
                      bufact += len;
105
                      break;
106
                    case 'L':
107
                      /* Use the current locale category value.  */
108
                      len = strlen (env_var);
109
                      ENOUGH (len);
110
                      memcpy (&buf[bufact], env_var, len);
111
                      bufact += len;
112
                      break;
113
                    case 'l':
114
                      /* Use language element of locale category value.  */
115
                      tmp = env_var;
116
                      do
117
                        {
118
                          ENOUGH (1);
119
                          buf[bufact++] = *tmp++;
120
                        }
121
                      while (*tmp != '\0' && *tmp != '_' && *tmp != '.');
122
                      break;
123
                    case 't':
124
                      /* Use territory element of locale category value.  */
125
                      tmp = env_var;
126
                      do
127
                        ++tmp;
128
                      while (*tmp != '\0' && *tmp != '_' && *tmp != '.');
129
                      if (*tmp == '_')
130
                        {
131
                          ++tmp;
132
                          do
133
                            {
134
                              ENOUGH (1);
135
                              buf[bufact++] = *tmp++;
136
                            }
137
                          while (*tmp != '\0' && *tmp != '.');
138
                        }
139
                      break;
140
                    case 'c':
141
                      /* Use code set element of locale category value.  */
142
                      tmp = env_var;
143
                      do
144
                        ++tmp;
145
                      while (*tmp != '\0' && *tmp != '.');
146
                      if (*tmp == '.')
147
                        {
148
                          ++tmp;
149
                          do
150
                            {
151
                              ENOUGH (1);
152
                              buf[bufact++] = *tmp++;
153
                            }
154
                          while (*tmp != '\0');
155
                        }
156
                      break;
157
                    case '%':
158
                      ENOUGH (1);
159
                      buf[bufact++] = '%';
160
                      break;
161
                    default:
162
                      /* Unknown variable: ignore this path element.  */
163
                      bufact = 0;
164
                      while (*run_nlspath != '\0' && *run_nlspath != ':')
165
                        ++run_nlspath;
166
                      break;
167
                    }
168
                }
169
              else
170
                {
171
                  ENOUGH (1);
172
                  buf[bufact++] = *run_nlspath++;
173
                }
174
 
175
          ENOUGH (1);
176
          buf[bufact] = '\0';
177
 
178
          if (bufact != 0)
179
            {
180
              fd = __open (buf, O_RDONLY);
181
              if (fd >= 0)
182
                break;
183
            }
184
 
185
          ++run_nlspath;
186
        }
187
    }
188
 
189
  /* Avoid dealing with directories and block devices */
190
  if (__builtin_expect (fd, 0) < 0)
191
    return -1;
192
 
193
  if (__builtin_expect (fstat64 (fd, &st), 0) < 0)
194
    goto close_unlock_return;
195
 
196
  if (__builtin_expect (!S_ISREG (st.st_mode), 0)
197
      || st.st_size < sizeof (struct catalog_obj))
198
    {
199
      /* `errno' is not set correctly but the file is not usable.
200
         Use an reasonable error value.  */
201
      __set_errno (EINVAL);
202
      goto close_unlock_return;
203
    }
204
 
205
  catalog->file_size = st.st_size;
206
#ifdef _POSIX_MAPPED_FILES
207
# ifndef MAP_COPY
208
    /* Linux seems to lack read-only copy-on-write.  */
209
#  define MAP_COPY MAP_PRIVATE
210
# endif
211
# ifndef MAP_FILE
212
    /* Some systems do not have this flag; it is superfluous.  */
213
#  define MAP_FILE 0
214
# endif
215
# ifndef MAP_INHERIT
216
    /* Some systems might lack this; they lose.  */
217
#  define MAP_INHERIT 0
218
# endif
219
  catalog->file_ptr =
220
    (struct catalog_obj *) __mmap (NULL, st.st_size, PROT_READ,
221
                                   MAP_FILE|MAP_COPY|MAP_INHERIT, fd, 0);
222
  if (__builtin_expect (catalog->file_ptr != (struct catalog_obj *) MAP_FAILED,
223
                        1))
224
    /* Tell the world we managed to mmap the file.  */
225
    catalog->status = mmapped;
226
  else
227
#endif /* _POSIX_MAPPED_FILES */
228
    {
229
      /* mmap failed perhaps because the system call is not
230
         implemented.  Try to load the file.  */
231
      size_t todo;
232
      catalog->file_ptr = malloc (st.st_size);
233
      if (catalog->file_ptr == NULL)
234
        goto close_unlock_return;
235
 
236
      todo = st.st_size;
237
      /* Save read, handle partial reads.  */
238
      do
239
        {
240
          size_t now = __read (fd, (((char *) catalog->file_ptr)
241
                                    + (st.st_size - todo)), todo);
242
          if (now == 0 || now == (size_t) -1)
243
            {
244
#ifdef EINTR
245
              if (now == (size_t) -1 && errno == EINTR)
246
                continue;
247
#endif
248
              free ((void *) catalog->file_ptr);
249
              goto close_unlock_return;
250
            }
251
          todo -= now;
252
        }
253
      while (todo > 0);
254
      catalog->status = malloced;
255
    }
256
 
257
  /* Determine whether the file is a catalog file and if yes whether
258
     it is written using the correct byte order.  Else we have to swap
259
     the values.  */
260
  if (__builtin_expect (catalog->file_ptr->magic, CATGETS_MAGIC)
261
      == CATGETS_MAGIC)
262
    swapping = 0;
263
  else if (catalog->file_ptr->magic == SWAPU32 (CATGETS_MAGIC))
264
    swapping = 1;
265
  else
266
    {
267
    invalid_file:
268
      /* Invalid file.  Free the resources and mark catalog as not
269
         usable.  */
270
#ifdef _POSIX_MAPPED_FILES
271
      if (catalog->status == mmapped)
272
        __munmap ((void *) catalog->file_ptr, catalog->file_size);
273
      else
274
#endif  /* _POSIX_MAPPED_FILES */
275
        free (catalog->file_ptr);
276
      goto close_unlock_return;
277
    }
278
 
279
#define SWAP(x) (swapping ? SWAPU32 (x) : (x))
280
 
281
  /* Get dimensions of the used hashing table.  */
282
  catalog->plane_size = SWAP (catalog->file_ptr->plane_size);
283
  catalog->plane_depth = SWAP (catalog->file_ptr->plane_depth);
284
 
285
  /* The file contains two versions of the pointer tables.  Pick the
286
     right one for the local byte order.  */
287
#if __BYTE_ORDER == __LITTLE_ENDIAN
288
  catalog->name_ptr = &catalog->file_ptr->name_ptr[0];
289
#elif __BYTE_ORDER == __BIG_ENDIAN
290
  catalog->name_ptr = &catalog->file_ptr->name_ptr[catalog->plane_size
291
                                                  * catalog->plane_depth
292
                                                  * 3];
293
#else
294
# error Cannot handle __BYTE_ORDER byte order
295
#endif
296
 
297
  /* The rest of the file contains all the strings.  They are
298
     addressed relative to the position of the first string.  */
299
  catalog->strings =
300
    (const char *) &catalog->file_ptr->name_ptr[catalog->plane_size
301
                                               * catalog->plane_depth * 3 * 2];
302
 
303
  /* Determine the largest string offset mentioned in the table.  */
304
  max_offset = 0;
305
  tab_size = 3 * catalog->plane_size * catalog->plane_depth;
306
  for (cnt = 2; cnt < tab_size; cnt += 3)
307
    if (catalog->name_ptr[cnt] > max_offset)
308
      max_offset = catalog->name_ptr[cnt];
309
 
310
  /* Now we can check whether the file is large enough to contain the
311
     tables it says it contains.  */
312
  if (st.st_size <= (sizeof (struct catalog_obj) + 2 * tab_size + max_offset))
313
    /* The last string is not contained in the file.  */
314
    goto invalid_file;
315
 
316
  lastp = catalog->strings + max_offset;
317
  max_offset = (st.st_size
318
                - sizeof (struct catalog_obj) + 2 * tab_size + max_offset);
319
  while (*lastp != '\0')
320
    {
321
      if (--max_offset == 0)
322
        goto invalid_file;
323
      ++lastp;
324
    }
325
 
326
  /* We succeeded.  */
327
  result = 0;
328
 
329
  /* Release the lock again.  */
330
 close_unlock_return:
331
  __close (fd);
332
 
333
  return result;
334
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.