[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#210460: locale -a doesn't list all available locales



Where did you get this patch from?  Is it in upstream CVS, or did you
write it yourself, or find it elsewhere?

We're trying to make sure that we stay as close to possible to upstream
CVS so will work towards getting this in if it's the right thing to do.

Tks,
Jeff Bailey

On Thu, Sep 11, 2003 at 01:22:10PM -0400, Adam Starling wrote:
> Package: libc6
> Version: 2.3.1
> 
> Part of the LSB Runtime Environment test suite uses checks several 
> executables for I18n compatibility.
> 
> locale failed the following test:
> 
> tp4()
> {
>        tet_infoline "* When -a option is specified, verify if this 
> utility writes information about all available public locales."
>        tet_infoline " "
> 
>        locale_initialize
>        export LANG=$targetlocale
> 
>        locale -a >out.stdout 2>out.stderr
>        (grep "^C" out.stdout && grep "^${targetlocale%.*}" out.stdout) 
> >/dev/null 2>&1
>        result_output_code $? "Can't print available locales."
> }
> 
> locale_initialize()
> {
>        unset LANG
>        for var in $LCVARS
>        do
>           unset $var
>        done
>        unset LC_ALL
> }
> 
> locale_posix()
> {
>    locale | grep "^LANG"
>    locale | grep "^LC_CTYPE"
>    locale | grep "^LC_TIME"
>    locale | grep "^LC_COLLATE"
>    locale | grep "^LC_MONETARY"
>    locale | grep "^LC_MESSAGES"
>    locale | grep "^LC_ALL"
> }
> 
> It only lists
> 
> C
> POSIX
> 
> The attached patch fixes the problem.  (modified list file included)

> #! /bin/sh -e
> 
> # DP: Fixes localization stuffsorz
> 
> if [ $# -ne 2 ]; then
> echo >&2 "`basename $0`: script expects -patch|-unpatch as argument"
> exit 1
> fi
> case "$1" in
> -patch) patch -d "$2" -f --no-backup-if-mismatch -p1 < $0;;
> -unpatch) patch -d "$2" -f --no-backup-if-mismatch -R -p1 < $0;;
> *)
> echo >&2 "`basename $0`: script expects -patch|-unpatch as argument"
> exit 1
> esac
> exit 0
> 
> --- glibc-2.3.1/locale/programs/locale.c	2003-01-11 18:13:57.000000000 +0000
> +++ glibc-2.3.1/locale/programs/locale.c	2003-01-11 18:13:59.000000000 +0000
> @@ -43,10 +43,12 @@
>  
>  #include "localeinfo.h"
>  #include "charmap-dir.h"
> +#include "../locarchive.h"
>  
>  extern void *xmalloc (size_t __n);
>  extern char *xstrdup (const char *__str);
>  
> +#define ARCHIVE_NAME LOCALEDIR "/locale-archive"
>  
>  /* If set print the name of the category.  */
>  static int show_category_name;
> @@ -168,7 +170,11 @@
>  			    int show_keyword_name);
>  
>  /* Prototypes for local functions.  */
> +static void print_LC_IDENTIFICATION (void *mapped, size_t size);
> +static void print_LC_CTYPE (void *mapped, size_t size);
>  static void write_locales (void);
> +static int nameentcmp (const void *a, const void *b);
> +static int write_archive_locales (void **all_datap, char *linebuf);
>  static void write_charmaps (void);
>  static void show_locale_vars (void);
>  static void show_info (const char *name);
> @@ -327,6 +333,74 @@
>  }
>  
>  
> +static void
> +print_LC_IDENTIFICATION (void *mapped, size_t size)
> +{
> +  /* Read the information from the file.  */
> +  struct
> +    {
> +      unsigned int magic;
> +      unsigned int nstrings;
> +      unsigned int strindex[0];
> +    } *filedata = mapped;
> +
> +  if (filedata->magic == LIMAGIC (LC_IDENTIFICATION)
> +      && (sizeof *filedata
> +	  + (filedata->nstrings
> +	     * sizeof (unsigned int))
> +	  <= size))
> +    {
> +      const char *str;
> +
> +#define HANDLE(idx, name) \
> +  str = ((char *) mapped						      \
> +	 + filedata->strindex[_NL_ITEM_INDEX (_NL_IDENTIFICATION_##idx)]);    \
> +  if (*str != '\0')							      \
> +    printf ("%9s | %s\n", name, str)
> +      HANDLE (TITLE, "title");
> +      HANDLE (SOURCE, "source");
> +      HANDLE (ADDRESS, "address");
> +      HANDLE (CONTACT, "contact");
> +      HANDLE (EMAIL, "email");
> +      HANDLE (TEL, "telephone");
> +      HANDLE (FAX, "fax");
> +      HANDLE (LANGUAGE, "language");
> +      HANDLE (TERRITORY, "territory");
> +      HANDLE (AUDIENCE, "audience");
> +      HANDLE (APPLICATION, "application");
> +      HANDLE (ABBREVIATION, "abbreviation");
> +      HANDLE (REVISION, "revision");
> +      HANDLE (DATE, "date");
> +    }
> +}
> +
> +
> +static void
> +print_LC_CTYPE (void *mapped, size_t size)
> +{
> +  struct
> +    {
> +      unsigned int magic;
> +      unsigned int nstrings;
> +      unsigned int strindex[0];
> +    } *filedata = mapped;
> +
> +  if (filedata->magic == LIMAGIC (LC_CTYPE)
> +      && (sizeof *filedata
> +	  + (filedata->nstrings
> +	     * sizeof (unsigned int))
> +	  <= size))
> +    {
> +      const char *str;
> +
> +      str = ((char *) mapped
> +	     + filedata->strindex[_NL_ITEM_INDEX (_NL_CTYPE_CODESET_NAME)]);
> +      if (*str != '\0')
> +	printf ("  codeset | %s\n", str);
> +    }
> +}
> +
> +
>  /* Write the names of all available locales to stdout.  We have some
>     sources of the information: the contents of the locale directory
>     and the locale.alias file.  To avoid duplicates and print the
> @@ -358,6 +432,10 @@
>    memset (linebuf, '-', sizeof (linebuf) - 1);
>    linebuf[sizeof (linebuf) - 1] = '\0';
>  
> +  /* First scan the locale archive.  */
> +  if (write_archive_locales (&all_data, linebuf))
> +    first_locale = 0;
> +
>    /* Now we can look for all files in the directory.  */
>    ndirents = scandir (LOCALEDIR, &dirents, select_dirs, alphasort);
>    for (cnt = 0; cnt < ndirents; ++cnt)
> @@ -375,7 +453,7 @@
>  
>        if (stat64 (buf, &st) == 0 && S_ISREG (st.st_mode))
>  	{
> -	  if (verbose)
> +	  if (verbose && GET (dirents[cnt]->d_name) == NULL)
>  	    {
>  	      /* Provide some nice output of all kinds of
>  		 information.  */
> @@ -396,42 +474,7 @@
>  					 MAP_SHARED, fd, 0);
>  		  if (mapped != MAP_FAILED)
>  		    {
> -		      /* Read the information from the file.  */
> -		      struct
> -		      {
> -			unsigned int magic;
> -			unsigned int nstrings;
> -			unsigned int strindex[0];
> -		      } *filedata = mapped;
> -
> -		      if (filedata->magic == LIMAGIC (LC_IDENTIFICATION)
> -			  && (sizeof *filedata
> -			      + (filedata->nstrings
> -				 * sizeof (unsigned int))
> -			      <= (size_t) st.st_size))
> -			{
> -			  const char *str;
> -
> -#define HANDLE(idx, name) \
> -  str = ((char *) mapped						      \
> -	 + filedata->strindex[_NL_ITEM_INDEX (_NL_IDENTIFICATION_##idx)]);    \
> -  if (*str != '\0')							      \
> -    printf ("%9s | %s\n", name, str)
> -			  HANDLE (TITLE, "title");
> -			  HANDLE (SOURCE, "source");
> -			  HANDLE (ADDRESS, "address");
> -			  HANDLE (CONTACT, "contact");
> -			  HANDLE (EMAIL, "email");
> -			  HANDLE (TEL, "telephone");
> -			  HANDLE (FAX, "fax");
> -			  HANDLE (LANGUAGE, "language");
> -			  HANDLE (TERRITORY, "territory");
> -			  HANDLE (AUDIENCE, "audience");
> -			  HANDLE (APPLICATION, "application");
> -			  HANDLE (ABBREVIATION, "abbreviation");
> -			  HANDLE (REVISION, "revision");
> -			  HANDLE (DATE, "date");
> -			}
> +		      print_LC_IDENTIFICATION (mapped, st.st_size);
>  
>  		      munmap (mapped, st.st_size);
>  		    }
> @@ -446,26 +489,7 @@
>  					    MAP_SHARED, fd, 0))
>  			  != MAP_FAILED))
>  		    {
> -		      struct
> -		      {
> -			unsigned int magic;
> -			unsigned int nstrings;
> -			unsigned int strindex[0];
> -		      } *filedata = mapped;
> -
> -		      if (filedata->magic == LIMAGIC (LC_CTYPE)
> -			  && (sizeof *filedata
> -			      + (filedata->nstrings
> -				 * sizeof (unsigned int))
> -			      <= (size_t) st.st_size))
> -			{
> -			  const char *str;
> -
> -			  str = ((char *) mapped
> -				 + filedata->strindex[_NL_ITEM_INDEX (_NL_CTYPE_CODESET_NAME)]);
> -			  if (*str != '\0')
> -			    printf ("  codeset | %s\n", str);
> -			}
> +		      print_LC_CTYPE (mapped, st.st_size);
>  
>  		      munmap (mapped, st.st_size);
>  		    }
> @@ -474,10 +498,10 @@
>  		    close (fd);
>  		}
>  	    }
> -	  else
> -	    /* If the verbose format is not selected we simply
> -	       collect the names.  */
> -	    PUT (xstrdup (dirents[cnt]->d_name));
> +
> +	  /* If the verbose format is not selected we simply
> +	     collect the names.  */
> +	  PUT (xstrdup (dirents[cnt]->d_name));
>  	}
>      }
>    if (ndirents > 0)
> @@ -584,6 +608,113 @@
>  }
>  
>  
> +struct nameent
> +{
> +  char *name;
> +  uint32_t locrec_offset;
> +};
> +
> +
> +static int
> +nameentcmp (const void *a, const void *b)
> +{
> +  return strcoll (((const struct nameent *) a)->name,
> +		  ((const struct nameent *) b)->name);
> +}
> +
> +
> +static int
> +write_archive_locales (void **all_datap, char *linebuf)
> +{
> +  struct stat64 st;
> +  void *all_data = *all_datap;
> +  size_t len = 0;
> +  struct locarhead *head;
> +  struct namehashent *namehashtab;
> +  char *addr = MAP_FAILED;
> +  int fd, ret = 0;
> +  uint32_t cnt;
> +
> +  fd = open64 (ARCHIVE_NAME, O_RDONLY);
> +  if (fd < 0)
> +    return 0;
> +
> +  if (fstat64 (fd, &st) < 0 || st.st_size < sizeof (*head))
> +    goto error_out;
> +
> +  len = st.st_size;
> +  addr = mmap64 (NULL, len, PROT_READ, MAP_SHARED, fd, 0);
> +  if (addr == MAP_FAILED)
> +    goto error_out;
> +
> +  head = (struct locarhead *) addr;
> +  if (head->namehash_offset + head->namehash_size > len
> +      || head->string_offset + head->string_size > len
> +      || head->locrectab_offset + head->locrectab_size > len
> +      || head->sumhash_offset + head->sumhash_size > len)
> +    goto error_out;
> +
> +  namehashtab = (struct namehashent *) (addr + head->namehash_offset);
> +  if (! verbose)
> +    {
> +      for (cnt = 0; cnt < head->namehash_size; ++cnt)
> +	if (namehashtab[cnt].locrec_offset != 0)
> +	  {
> +	    PUT (xstrdup (addr + namehashtab[cnt].name_offset));
> +	    ++ret;
> +	  }
> +    }
> +  else
> +    {
> +      struct nameent *names;
> +      uint32_t used;
> +
> +      names = (struct nameent *) xmalloc (head->namehash_used
> +					  * sizeof (struct nameent));
> +      for (cnt = used = 0; cnt < head->namehash_size; ++cnt)
> +	if (namehashtab[cnt].locrec_offset != 0)
> +	  {
> +	    names[used].name = addr + namehashtab[cnt].name_offset;
> +	    names[used++].locrec_offset = namehashtab[cnt].locrec_offset;
> +	  }
> +
> +      /* Sort the names.  */
> +      qsort (names, used, sizeof (struct nameent), nameentcmp);
> +
> +      for (cnt = 0; cnt < used; ++cnt)
> +	{
> +	  struct locrecent *locrec;
> +
> +	  PUT (xstrdup (names[cnt].name));
> +
> +	  if (cnt)
> +	    putchar_unlocked ('\n');
> +
> +	  printf ("locale: %-15.15s archive: " ARCHIVE_NAME "\n%s\n",
> +		  names[cnt].name, linebuf);
> +
> +	  locrec = (struct locrecent *) (addr + names[cnt].locrec_offset);
> +
> +	  print_LC_IDENTIFICATION (addr
> +				   + locrec->record[LC_IDENTIFICATION].offset,
> +				   locrec->record[LC_IDENTIFICATION].len);
> +
> +	  print_LC_CTYPE (addr + locrec->record[LC_CTYPE].offset,
> +			  locrec->record[LC_CTYPE].len);
> +	}
> +
> +      ret = used;
> +    }
> +
> +error_out:
> +  if (addr != MAP_FAILED)
> +    munmap (addr, len);
> +  close (fd);
> +  *all_datap = all_data;
> +  return ret;
> +}
> +
> +
>  /* Write the names of all available character maps to stdout.  */
>  static void
>  write_charmaps (void)

> cvs
> makeconfig
> locale-es_AR
> ldconfig
> ldd
> glibcbug
> fhs-linux-paths
> # JB - 44697 string2-pointer-arith
> glibc22-nss-upgrade
> #glibc22-getaddrinfo - Update for post 2.3.1 CVS
> glibc22-eo_EO
> glibc22-m68k-compat
> glibc22-m68k-fpic
> glibc22-locales
> sparc64-fixups
> #glibc22-getdents-fix - There's a workaround in the kernel. Upstream refused this.
> glibc22-ttyname-devfs
> powerpc-sysconf
> #ip6-fix - Bug#165287
> arm-no-hwcap
> locales-stuff
> #JB - Update for 2.3? ia64-reloc-none
> nscd-security-fix
> #JB - Update for 2.3 ia64-perf
> #ldso-disable-hwcap	- remove due to disabling hwcap is not good way.
> elf-machine-rela-mips
> librt-mips
> glibc23-ctype-compat
> #rtsig
> #crypt
> #s390x-lib64
> #hurd-fork-fix
> #glibc23-00-hppa-pthreads
> glibc23-01-hppa-dl-machine
> glibc23-07-hppa-atomicity
> signal-texi
> #s390-types
> glibc23-ia64-strncpy
> glibc23-hppa-Rminkernel
> glibc23-function-compat
> glibc23-getdents64-fix
> glibc23-errno
> glibc23-getaddrinfo
> glibc23-hppa-shmlba
> document-fix
> glibc23-asserth-decls
> alpha-pic
> glibc23-cmov
> glibc23-regcomp
> libgcc-compat-all
> glibc23-malloc-check
> locales-supported
> glibc23-hppa-compat
> libgcc-compat-other
> glibc23-m68k-madv
> glibc23-00-hppa-pthreads 
> glibc23-hppa-malloc8
> glibc23-cert-rpcxdr
> glibc-2.3.1-locale




Reply to: