Back to index

glibc  2.9
Classes | Defines | Enumerations | Functions | Variables
localedef.h File Reference
#include <errno.h>
#include <locale.h>
#include <stdbool.h>
#include <stddef.h>
#include "repertoire.h"
#include "../locarchive.h"
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Classes

struct  localedef_t
union  localedef_t.categories

Defines

#define WITH_CUR_LOCALE(stmt)

Enumerations

enum  {
  CTYPE_LOCALE = 1 << LC_CTYPE, NUMERIC_LOCALE = 1 << LC_NUMERIC, TIME_LOCALE = 1 << LC_TIME, COLLATE_LOCALE = 1 << LC_COLLATE,
  MONETARY_LOCALE = 1 << LC_MONETARY, MESSAGES_LOCALE = 1 << LC_MESSAGES, PAPER_LOCALE = 1 << LC_PAPER, NAME_LOCALE = 1 << LC_NAME,
  ADDRESS_LOCALE = 1 << LC_ADDRESS, TELEPHONE_LOCALE = 1 << LC_TELEPHONE, MEASUREMENT_LOCALE = 1 << LC_MEASUREMENT, IDENTIFICATION_LOCALE = 1 << LC_IDENTIFICATION,
  ALL_LOCALES
}

Functions

void * xmalloc (size_t __n)
void * xcalloc (size_t __n, size_t __size)
void * xrealloc (void *__p, size_t __n)
char * xstrdup (const char *__str)
struct localedef_tadd_to_readlist (int locale, const char *name, const char *repertoire_name, int generate, struct localedef_t *copy_locale)
struct localedef_tfind_locale (int locale, const char *name, const char *repertoire_name, const struct charmap_t *charmap)
struct localedef_tload_locale (int locale, const char *name, const char *repertoire_name, const struct charmap_t *charmap, struct localedef_t *copy_locale)
void open_archive (struct locarhandle *ah, bool readonly)
void close_archive (struct locarhandle *ah)
int add_locale_to_archive (struct locarhandle *ah, const char *name, locale_data_t data, bool replace)
int add_locales_to_archive (size_t nlist, char *list[], bool replace)
int delete_locales_from_archive (size_t nlist, char *list[])
void show_archive_content (int verbose)

Variables

int verbose
int be_quiet
int oldstyle_tables
const char * repertoire_global
int max_locarchive_open_retry
bool no_archive
const char * alias_file

Class Documentation

struct localedef_t

Definition at line 79 of file localedef.h.

Collaboration diagram for localedef_t:
Class Members
int avail
union localedef_t categories
const char * copy_name
size_t len
const char * name
int needed
struct localedef_t * next
const char * repertoire_name
union localedef_t.categories

Definition at line 88 of file localedef.h.

Class Members
struct locale_address_t * address
struct locale_collate_t * collate
struct locale_ctype_t * ctype
void * generic
struct locale_identification_t * identification
struct locale_measurement_t * measurement
struct locale_messages_t * messages
struct locale_monetary_t * monetary
struct locale_name_t * name
struct locale_numeric_t * numeric
struct locale_paper_t * paper
struct locale_telephone_t * telephone
struct locale_time_t * time

Define Documentation

#define WITH_CUR_LOCALE (   stmt)
Value:
do {                                                    \
      int saved_errno = errno;                                 \
      const char *cur_locale_ = setlocale (LC_CTYPE, NULL);    \
      setlocale (LC_CTYPE, "");                                \
      errno = saved_errno;                              \
      stmt;                                             \
      setlocale (LC_CTYPE, cur_locale_);                \
  } while (0)

Definition at line 132 of file localedef.h.


Enumeration Type Documentation

anonymous enum
Enumerator:
CTYPE_LOCALE 
NUMERIC_LOCALE 
TIME_LOCALE 
COLLATE_LOCALE 
MONETARY_LOCALE 
MESSAGES_LOCALE 
PAPER_LOCALE 
NAME_LOCALE 
ADDRESS_LOCALE 
TELEPHONE_LOCALE 
MEASUREMENT_LOCALE 
IDENTIFICATION_LOCALE 
ALL_LOCALES 

Definition at line 34 of file localedef.h.


Function Documentation

int add_locale_to_archive ( struct locarhandle ah,
const char *  name,
locale_data_t  data,
bool  replace 
)

Definition at line 926 of file locarchive.c.

{
  char *normalized_name = NULL;
  uint32_t locrec_offset;

  /* First analyze the name to decide how to archive it.  */
  const char *language;
  const char *modifier;
  const char *territory;
  const char *codeset;
  const char *normalized_codeset;
  int mask = _nl_explode_name (strdupa (name),
                            &language, &modifier, &territory,
                            &codeset, &normalized_codeset);

  if (mask & XPG_NORM_CODESET)
    /* This name contains a codeset in unnormalized form.
       We will store it in the archive with a normalized name.  */
    asprintf (&normalized_name, "%s%s%s.%s%s%s",
             language, territory == NULL ? "" : "_", territory ?: "",
             (mask & XPG_NORM_CODESET) ? normalized_codeset : codeset,
             modifier == NULL ? "" : "@", modifier ?: "");

  /* This call does the main work.  */
  locrec_offset = add_locale (ah, normalized_name ?: name, data, replace);
  if (locrec_offset == 0)
    {
      free (normalized_name);
      if (mask & XPG_NORM_CODESET)
       free ((char *) normalized_codeset);
      return -1;
    }

  if ((mask & XPG_CODESET) == 0)
    {
      /* This name lacks a codeset, so determine the locale's codeset and
        add an alias for its name with normalized codeset appended.  */

      const struct
      {
       unsigned int magic;
       unsigned int nstrings;
       unsigned int strindex[0];
      } *filedata = data[LC_CTYPE].addr;
      codeset = (char *) filedata
       + filedata->strindex[_NL_ITEM_INDEX (_NL_CTYPE_CODESET_NAME)];
      char *normalized_codeset_name = NULL;

      normalized_codeset = _nl_normalize_codeset (codeset, strlen (codeset));
      mask |= XPG_NORM_CODESET;

      asprintf (&normalized_codeset_name, "%s%s%s.%s%s%s",
              language, territory == NULL ? "" : "_", territory ?: "",
              normalized_codeset,
              modifier == NULL ? "" : "@", modifier ?: "");

      add_alias (ah, normalized_codeset_name, replace,
               normalized_name ?: name, &locrec_offset);
      free (normalized_codeset_name);
    }

  /* Now read the locale.alias files looking for lines whose
     right hand side matches our name after normalization.  */
  if (alias_file != NULL)
    {
      FILE *fp;
      fp = fopen (alias_file, "rm");
      if (fp == NULL)
       error (1, errno, _("locale alias file `%s' not found"),
              alias_file);

      /* No threads present.  */
      __fsetlocking (fp, FSETLOCKING_BYCALLER);

      while (! feof_unlocked (fp))
       {
         /* It is a reasonable approach to use a fix buffer here
            because
            a) we are only interested in the first two fields
            b) these fields must be usable as file names and so must
            not be that long  */
         char buf[BUFSIZ];
         char *alias;
         char *value;
         char *cp;

         if (fgets_unlocked (buf, BUFSIZ, fp) == NULL)
           /* EOF reached.  */
           break;

         cp = buf;
         /* Ignore leading white space.  */
         while (isspace (cp[0]) && cp[0] != '\n')
           ++cp;

         /* A leading '#' signals a comment line.  */
         if (cp[0] != '\0' && cp[0] != '#' && cp[0] != '\n')
           {
             alias = cp++;
             while (cp[0] != '\0' && !isspace (cp[0]))
              ++cp;
             /* Terminate alias name.  */
             if (cp[0] != '\0')
              *cp++ = '\0';

             /* Now look for the beginning of the value.  */
             while (isspace (cp[0]))
              ++cp;

             if (cp[0] != '\0')
              {
                value = cp++;
                while (cp[0] != '\0' && !isspace (cp[0]))
                  ++cp;
                /* Terminate value.  */
                if (cp[0] == '\n')
                  {
                    /* This has to be done to make the following
                      test for the end of line possible.  We are
                      looking for the terminating '\n' which do not
                      overwrite here.  */
                    *cp++ = '\0';
                    *cp = '\n';
                  }
                else if (cp[0] != '\0')
                  *cp++ = '\0';

                /* Does this alias refer to our locale?  We will
                   normalize the right hand side and compare the
                   elements of the normalized form.  */
                {
                  const char *rhs_language;
                  const char *rhs_modifier;
                  const char *rhs_territory;
                  const char *rhs_codeset;
                  const char *rhs_normalized_codeset;
                  int rhs_mask = _nl_explode_name (value,
                                               &rhs_language,
                                               &rhs_modifier,
                                               &rhs_territory,
                                               &rhs_codeset,
                                               &rhs_normalized_codeset);
                  if (!strcmp (language, rhs_language)
                     && ((rhs_mask & XPG_CODESET)
                         /* He has a codeset, it must match normalized.  */
                         ? !strcmp ((mask & XPG_NORM_CODESET)
                                   ? normalized_codeset : codeset,
                                   (rhs_mask & XPG_NORM_CODESET)
                                   ? rhs_normalized_codeset : rhs_codeset)
                         /* He has no codeset, we must also have none.  */
                         : (mask & XPG_CODESET) == 0)
                     /* Codeset (or lack thereof) matches.  */
                     && !strcmp (territory ?: "", rhs_territory ?: "")
                     && !strcmp (modifier ?: "", rhs_modifier ?: ""))
                    /* We have a winner.  */
                    add_alias (ah, alias, replace,
                             normalized_name ?: name, &locrec_offset);
                  if (rhs_mask & XPG_NORM_CODESET)
                    free ((char *) rhs_normalized_codeset);
                }
              }
           }

         /* Possibly not the whole line fits into the buffer.
            Ignore the rest of the line.  */
         while (strchr (cp, '\n') == NULL)
           {
             cp = buf;
             if (fgets_unlocked (buf, BUFSIZ, fp) == NULL)
              /* Make sure the inner loop will be left.  The outer
                 loop will exit at the `feof' test.  */
              *cp = '\n';
           }
       }

      fclose (fp);
    }

  free (normalized_name);

  if (mask & XPG_NORM_CODESET)
    free ((char *) normalized_codeset);

  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int add_locales_to_archive ( size_t  nlist,
char *  list[],
bool  replace 
)

Here is the caller graph for this function:

struct localedef_t* add_to_readlist ( int  locale,
const char *  name,
const char *  repertoire_name,
int  generate,
struct localedef_t copy_locale 
) [read]

Definition at line 534 of file localedef.c.

{
  struct localedef_t *runp = locales;

  while (runp != NULL && strcmp (name, runp->name) != 0)
    runp = runp->next;

  if (runp == NULL)
    {
      /* Add a new entry at the end.  */
      struct localedef_t *newp;

      assert (generate == 1);

      newp = xcalloc (1, sizeof (struct localedef_t));
      newp->name = name;
      newp->repertoire_name = repertoire_name;

      if (locales == NULL)
       runp = locales = newp;
      else
       {
         runp = locales;
         while (runp->next != NULL)
           runp = runp->next;
         runp = runp->next = newp;
       }
    }

  if (generate
      && (runp->needed & (1 << category)) != 0
      && (runp->avail & (1 << category)) == 0)
    WITH_CUR_LOCALE (error (5, 0, _("\
circular dependencies between locale definitions")));

  if (copy_locale != NULL)
    {
      if (runp->categories[category].generic != NULL)
       WITH_CUR_LOCALE (error (5, 0, _("\
cannot add already read locale `%s' a second time"), name));
      else
       runp->categories[category].generic =
         copy_locale->categories[category].generic;
    }

  runp->needed |= 1 << category;

  return runp;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void close_archive ( struct locarhandle ah)

Definition at line 533 of file locarchive.c.

{
  if (ah->fd != -1)
    {
      munmap (ah->addr, ah->len);
      close (ah->fd);
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

int delete_locales_from_archive ( size_t  nlist,
char *  list[] 
)

Here is the caller graph for this function:

struct localedef_t* find_locale ( int  locale,
const char *  name,
const char *  repertoire_name,
const struct charmap_t charmap 
) [read]

Definition at line 587 of file localedef.c.

{
  struct localedef_t *result;

  /* Find the locale, but do not generate it since this would be a bug.  */
  result = add_to_readlist (category, name, repertoire_name, 0, NULL);

  assert (result != NULL);

  if ((result->avail & (1 << category)) == 0
      && locfile_read (result, charmap) != 0)
    WITH_CUR_LOCALE (error (4, errno, _("\
cannot open locale definition file `%s'"), result->name));

  return result;
}

Here is the call graph for this function:

Here is the caller graph for this function:

struct localedef_t* load_locale ( int  locale,
const char *  name,
const char *  repertoire_name,
const struct charmap_t charmap,
struct localedef_t copy_locale 
) [read]

Definition at line 607 of file localedef.c.

{
  struct localedef_t *result;

  /* Generate the locale if it does not exist.  */
  result = add_to_readlist (category, name, repertoire_name, 1, copy_locale);

  assert (result != NULL);

  if ((result->avail & (1 << category)) == 0
      && locfile_read (result, charmap) != 0)
    WITH_CUR_LOCALE (error (4, errno, _("\
cannot open locale definition file `%s'"), result->name));

  return result;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void open_archive ( struct locarhandle ah,
bool  readonly 
)

Definition at line 425 of file locarchive.c.

{
  struct stat64 st;
  struct stat64 st2;
  int fd;
  struct locarhead head;
  int retry = 0;
  size_t prefix_len = output_prefix ? strlen (output_prefix) : 0;
  char archivefname[prefix_len + sizeof (ARCHIVE_NAME)];

  if (output_prefix)
    memcpy (archivefname, output_prefix, prefix_len);
  strcpy (archivefname + prefix_len, ARCHIVE_NAME);

  while (1)
    {
      /* Open the archive.  We must have exclusive write access.  */
      fd = open64 (archivefname, readonly ? O_RDONLY : O_RDWR);
      if (fd == -1)
       {
         /* Maybe the file does not yet exist.  */
         if (errno == ENOENT)
           {
             if (readonly)
              {
                static const struct locarhead nullhead =
                  {
                    .namehash_used = 0,
                    .namehash_offset = 0,
                    .namehash_size = 0
                  };

                ah->addr = (void *) &nullhead;
                ah->fd = -1;
              }
             else
              create_archive (archivefname, ah);

             return;
           }
         else
           error (EXIT_FAILURE, errno, _("cannot open locale archive \"%s\""),
                 archivefname);
       }

      if (fstat64 (fd, &st) < 0)
       error (EXIT_FAILURE, errno, _("cannot stat locale archive \"%s\""),
              archivefname);

      if (!readonly && lockf64 (fd, F_LOCK, sizeof (struct locarhead)) == -1)
       {
         close (fd);

         if (retry++ < max_locarchive_open_retry)
           {
             struct timespec req;

             /* Wait for a bit.  */
             req.tv_sec = 0;
             req.tv_nsec = 1000000 * (random () % 500 + 1);
             (void) nanosleep (&req, NULL);

             continue;
           }

         error (EXIT_FAILURE, errno, _("cannot lock locale archive \"%s\""),
               archivefname);
       }

      /* One more check.  Maybe another process replaced the archive file
        with a new, larger one since we opened the file.  */
      if (stat64 (archivefname, &st2) == -1
         || st.st_dev != st2.st_dev
         || st.st_ino != st2.st_ino)
       {
         (void) lockf64 (fd, F_ULOCK, sizeof (struct locarhead));
         close (fd);
         continue;
       }

      /* Leave the loop.  */
      break;
    }

  /* Read the header.  */
  if (TEMP_FAILURE_RETRY (read (fd, &head, sizeof (head))) != sizeof (head))
    {
      (void) lockf64 (fd, F_ULOCK, sizeof (struct locarhead));
      error (EXIT_FAILURE, errno, _("cannot read archive header"));
    }

  ah->fd = fd;
  ah->len = (head.sumhash_offset
            + head.sumhash_size * sizeof (struct sumhashent));

  /* Now we know how large the administrative information part is.
     Map all of it.  */
  ah->addr = mmap64 (NULL, ah->len, PROT_READ | (readonly ? 0 : PROT_WRITE),
                   MAP_SHARED, fd, 0);
  if (ah->addr == MAP_FAILED)
    {
      (void) lockf64 (fd, F_ULOCK, sizeof (struct locarhead));
      error (EXIT_FAILURE, errno, _("cannot map archive header"));
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

void show_archive_content ( int  verbose)

Definition at line 1415 of file locarchive.c.

{
  struct locarhandle ah;
  struct locarhead *head;
  struct namehashent *namehashtab;
  struct nameent *names;
  size_t cnt, used;

  /* Open the archive.  This call never returns if we cannot
     successfully open the archive.  */
  open_archive (&ah, true);

  head = ah.addr;

  names = (struct nameent *) xmalloc (head->namehash_used
                                  * sizeof (struct nameent));

  namehashtab = (struct namehashent *) ((char *) ah.addr
                                   + head->namehash_offset);
  for (cnt = used = 0; cnt < head->namehash_size; ++cnt)
    if (namehashtab[cnt].locrec_offset != 0)
      {
       assert (used < head->namehash_used);
       names[used].name = ah.addr + namehashtab[cnt].name_offset;
       names[used++].locrec_offset = namehashtab[cnt].locrec_offset;
      }

  /* Sort the names.  */
  qsort (names, used, sizeof (struct nameent), nameentcmp);

  if (verbose)
    {
      struct dataent *files;
      struct sumhashent *sumhashtab;
      int sumused;

      files = (struct dataent *) xmalloc (head->sumhash_used
                                     * sizeof (struct dataent));

      sumhashtab = (struct sumhashent *) ((char *) ah.addr
                                     + head->sumhash_offset);
      for (cnt = sumused = 0; cnt < head->sumhash_size; ++cnt)
       if (sumhashtab[cnt].file_offset != 0)
         {
           assert (sumused < head->sumhash_used);
           files[sumused].sum = (const unsigned char *) sumhashtab[cnt].sum;
           files[sumused].file_offset = sumhashtab[cnt].file_offset;
           files[sumused++].nlink = 0;
         }

      /* Sort by file locations.  */
      qsort (files, sumused, sizeof (struct dataent), dataentcmp);

      /* Compute nlink fields.  */
      for (cnt = 0; cnt < used; ++cnt)
       {
         struct locrecent *locrec;
         int idx;

         locrec = (struct locrecent *) ((char *) ah.addr
                                    + names[cnt].locrec_offset);
         for (idx = 0; idx < __LC_LAST; ++idx)
           if (locrec->record[LC_ALL].offset != 0
              ? (idx == LC_ALL
                 || (locrec->record[idx].offset
                     < locrec->record[LC_ALL].offset)
                 || (locrec->record[idx].offset + locrec->record[idx].len
                     > (locrec->record[LC_ALL].offset
                       + locrec->record[LC_ALL].len)))
              : idx != LC_ALL)
             {
              struct dataent *data, dataent;

              dataent.file_offset = locrec->record[idx].offset;
              data = (struct dataent *) bsearch (&dataent, files, sumused,
                                             sizeof (struct dataent),
                                             dataentcmp);
              assert (data != NULL);
              ++data->nlink;
             }
       }

      /* Print it.  */
      for (cnt = 0; cnt < used; ++cnt)
       {
         struct locrecent *locrec;
         int idx, i;

         locrec = (struct locrecent *) ((char *) ah.addr
                                    + names[cnt].locrec_offset);
         for (idx = 0; idx < __LC_LAST; ++idx)
           if (idx != LC_ALL)
             {
              struct dataent *data, dataent;

              dataent.file_offset = locrec->record[idx].offset;
              if (locrec->record[LC_ALL].offset != 0
                  && dataent.file_offset >= locrec->record[LC_ALL].offset
                  && (dataent.file_offset + locrec->record[idx].len
                     <= (locrec->record[LC_ALL].offset
                         + locrec->record[LC_ALL].len)))
                dataent.file_offset = locrec->record[LC_ALL].offset;

              data = (struct dataent *) bsearch (&dataent, files, sumused,
                                             sizeof (struct dataent),
                                             dataentcmp);
              printf ("%6d %7x %3d%c ",
                     locrec->record[idx].len, locrec->record[idx].offset,
                     data->nlink,
                     dataent.file_offset == locrec->record[LC_ALL].offset
                     ? '+' : ' ');
              for (i = 0; i < 16; i += 4)
                  printf ("%02x%02x%02x%02x",
                         data->sum[i], data->sum[i + 1],
                         data->sum[i + 2], data->sum[i + 3]);
              printf (" %s/%s\n", names[cnt].name,
                     idx == LC_MESSAGES ? "LC_MESSAGES/SYS_LC_MESSAGES"
                     : locnames[idx]);
             }
       }
    }
  else
    for (cnt = 0; cnt < used; ++cnt)
      puts (names[cnt].name);

  close_archive (&ah);

  exit (EXIT_SUCCESS);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void* xcalloc ( size_t  __n,
size_t  __size 
)

Definition at line 91 of file xmalloc.c.

{
  VOID *p;

  p = calloc (n, s);
  if (p == 0)
    p = fixup_null_alloc (n);
  return p;
}
void* xmalloc ( size_t  __n)

Definition at line 77 of file xmalloc.c.

{
  VOID *p;

  p = malloc (n);
  if (p == 0)
    p = fixup_null_alloc (n);
  return p;
}
void* xrealloc ( void *  __p,
size_t  __n 
)
char* xstrdup ( const char *  __str)

Variable Documentation

Definition at line 79 of file localedef.c.

Definition at line 57 of file localedef.c.

Definition at line 100 of file localedef.c.

bool no_archive

Definition at line 85 of file localedef.c.

Definition at line 61 of file localedef.c.

Definition at line 76 of file localedef.c.

Definition at line 102 of file iconv_prog.c.