New approach to including locale data in the rpm.
authorjakub <jakub>
Mon, 16 Apr 2007 22:55:49 +0000 (22:55 +0000)
committerjakub <jakub>
Mon, 16 Apr 2007 22:55:49 +0000 (22:55 +0000)
ChangeLog
fedora/build-locale-archive.c
fedora/glibc.spec.in
locale/programs/locarchive.c

index 0eff012..b54e3bc 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+2007-04-16  Jakub Jelinek  <jakub@redhat.com>
+
+       * locale/programs/locarchive.c (add_alias, insert_name): Remove static.
+
 2007-03-23  Jakub Jelinek  <jakub@redhat.com>
 
        * scripts/check-local-headers.sh: Filter out sys/capability.h.
index a351717..ef0ac91 100644 (file)
@@ -1,23 +1,39 @@
 #define _GNU_SOURCE
-#include <stdlib.h>
-#include <unistd.h>
+#include <assert.h>
 #include <dirent.h>
 #include <errno.h>
-#include <string.h>
+#include <fcntl.h>
+#include <locale.h>
+#include <stdarg.h>
 #include <stdbool.h>
-#include <sys/stat.h>
 #include <stdio.h>
-#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <unistd.h>
 #include "../locale/hashval.h"
+#define __LC_LAST 13
+#include "../locale/locarchive.h"
+#include "../crypt/md5.h"
 
 const char *alias_file = DATADIR "/locale/locale.alias";
 const char *locar_file = PREFIX "/lib/locale/locale-archive";
+const char *tmpl_file = PREFIX "/lib/locale/locale-archive.tmpl";
 const char *loc_path = PREFIX "/lib/locale/";
 int be_quiet = 1;
 int verbose = 0;
 int max_locarchive_open_retry = 10;
 const char *output_prefix;
 
+static const char *locnames[] =
+  {
+#define DEFINE_CATEGORY(category, category_name, items, a) \
+  [category] = category_name,
+#include "../locale/categories.def"
+#undef  DEFINE_CATEGORY
+  };
+
 static int
 is_prime (unsigned long candidate)
 {
@@ -51,6 +67,7 @@ next_prime (unsigned long seed)
 void *
 xmalloc (size_t size)
 {
+  (void) size;
   exit (255);
 }
 
@@ -72,7 +89,446 @@ error (int status, int errnum, const char *message, ...)
     exit (errnum == EROFS ? 0 : status);
 }
 
-extern int add_locales_to_archive (size_t nlist, char *list[], bool replace);
+static void
+open_tmpl_archive (struct locarhandle *ah)
+{
+  struct stat64 st;
+  int fd;
+  struct locarhead head;
+  const char *archivefname = tmpl_file;
+
+  /* Open the archive.  We must have exclusive write access.  */
+  fd = open64 (archivefname, O_RDONLY);
+  if (fd == -1)
+    error (EXIT_FAILURE, errno, "cannot open locale archive template file \"%s\"",
+          archivefname);
+
+  if (fstat64 (fd, &st) < 0)
+    error (EXIT_FAILURE, errno, "cannot stat locale archive template file \"%s\"",
+          archivefname);
+
+  /* Read the header.  */
+  if (TEMP_FAILURE_RETRY (read (fd, &head, sizeof (head))) != sizeof (head))
+    error (EXIT_FAILURE, errno, "cannot read archive header");
+
+  ah->fd = fd;
+  ah->len = (head.sumhash_offset
+            + head.sumhash_size * sizeof (struct sumhashent));
+  if (ah->len > st.st_size)
+    error (EXIT_FAILURE, 0, "locale archite template file truncated");
+  ah->len = st.st_size;
+
+  /* Now we know how large the administrative information part is.
+     Map all of it.  */
+  ah->addr = mmap64 (NULL, ah->len, PROT_READ, MAP_SHARED, fd, 0);
+  if (ah->addr == MAP_FAILED)
+    error (EXIT_FAILURE, errno, "cannot map archive header");
+}
+
+/* Open the locale archive.  */
+extern void open_archive (struct locarhandle *ah, bool readonly);
+
+/* Close the locale archive.  */
+extern void close_archive (struct locarhandle *ah);
+
+/* Add given locale data to the archive.  */
+extern int add_locale_to_archive (struct locarhandle *ah, const char *name,
+                                 locale_data_t data, bool replace);
+
+extern void add_alias (struct locarhandle *ah, const char *alias,
+                      bool replace, const char *oldname,
+                      uint32_t *locrec_offset_p);
+
+extern struct namehashent *
+insert_name (struct locarhandle *ah,
+            const char *name, size_t name_len, bool replace);
+
+struct nameent
+{
+  char *name;
+  struct locrecent *locrec;
+};
+
+struct dataent
+{
+  const unsigned char *sum;
+  uint32_t file_offset;
+};
+
+static int
+nameentcmp (const void *a, const void *b)
+{
+  struct locrecent *la = ((const struct nameent *) a)->locrec;
+  struct locrecent *lb = ((const struct nameent *) b)->locrec;
+  uint32_t start_a = -1, end_a = 0;
+  uint32_t start_b = -1, end_b = 0;
+  int cnt;
+
+  for (cnt = 0; cnt < __LC_LAST; ++cnt)
+    if (cnt != LC_ALL)
+      {
+       if (la->record[cnt].offset < start_a)
+         start_a = la->record[cnt].offset;
+       if (la->record[cnt].offset + la->record[cnt].len > end_a)
+         end_a = la->record[cnt].offset + la->record[cnt].len;
+      }
+  assert (start_a != (uint32_t)-1);
+  assert (end_a != 0);
+
+  for (cnt = 0; cnt < __LC_LAST; ++cnt)
+    if (cnt != LC_ALL)
+      {
+       if (lb->record[cnt].offset < start_b)
+         start_b = lb->record[cnt].offset;
+       if (lb->record[cnt].offset + lb->record[cnt].len > end_b)
+         end_b = lb->record[cnt].offset + lb->record[cnt].len;
+      }
+  assert (start_b != (uint32_t)-1);
+  assert (end_b != 0);
+
+  if (start_a != start_b)
+    return (int)start_a - (int)start_b;
+  return (int)end_a - (int)end_b;
+}
+
+static int
+dataentcmp (const void *a, const void *b)
+{
+  if (((const struct dataent *) a)->file_offset
+      < ((const struct dataent *) b)->file_offset)
+    return -1;
+
+  if (((const struct dataent *) a)->file_offset
+      > ((const struct dataent *) b)->file_offset)
+    return 1;
+
+  return 0;
+}
+
+static int
+sumsearchfn (const void *key, const void *ent)
+{
+  uint32_t keyn = *(uint32_t *)key;
+  uint32_t entn = ((struct dataent *)ent)->file_offset;
+
+  if (keyn < entn)
+    return -1;
+  if (keyn > entn)
+    return 1;
+  return 0;
+}
+
+static void
+compute_data (struct locarhandle *ah, struct nameent *name, size_t sumused,
+             struct dataent *files, locale_data_t data)
+{
+  int cnt;
+  struct locrecent *locrec = name->locrec;
+  struct dataent *file;
+  data[LC_ALL].addr = ((char *) ah->addr) + locrec->record[LC_ALL].offset;
+  data[LC_ALL].size = locrec->record[LC_ALL].len;
+  for (cnt = 0; cnt < __LC_LAST; ++cnt)
+    if (cnt != LC_ALL)
+      {
+       data[cnt].addr = ((char *) ah->addr) + locrec->record[cnt].offset;
+       data[cnt].size = locrec->record[cnt].len;
+       if (data[cnt].addr >= data[LC_ALL].addr
+           && data[cnt].addr + data[cnt].size
+              <= data[LC_ALL].addr + data[LC_ALL].size)
+         __md5_buffer (data[cnt].addr, data[cnt].size, data[cnt].sum);
+       else
+         {
+           file = bsearch (&locrec->record[cnt].offset, files, sumused,
+                           sizeof (*files), sumsearchfn);
+           if (file == NULL)
+             error (EXIT_FAILURE, 0, "inconsistent template file");
+           memcpy (data[cnt].sum, file->sum, sizeof (data[cnt].sum));
+         }
+      }
+}
+
+static int
+fill_archive (struct locarhandle *tmpl_ah, size_t nlist, char *list[],
+             const char *primary)
+{
+  struct locarhandle ah;
+  struct locarhead *head;
+  int result = 0;
+  struct nameent *names;
+  struct namehashent *namehashtab;
+  size_t cnt, used;
+  struct dataent *files;
+  struct sumhashent *sumhashtab;
+  size_t sumused;
+  struct locrecent *primary_locrec = NULL;
+  struct nameent *primary_nameent = NULL;
+
+  head = tmpl_ah->addr;
+  names = (struct nameent *) malloc (head->namehash_used
+                                    * sizeof (struct nameent));
+  files = (struct dataent *) malloc (head->sumhash_used
+                                    * sizeof (struct dataent));
+  if (names == NULL || files == NULL)
+    error (EXIT_FAILURE, errno, "could not allocate tables");
+
+  namehashtab = (struct namehashent *) ((char *) tmpl_ah->addr
+                                       + head->namehash_offset);
+  sumhashtab = (struct sumhashent *) ((char *) tmpl_ah->addr
+                                     + head->sumhash_offset);
+
+  for (cnt = used = 0; cnt < head->namehash_size; ++cnt)
+    if (namehashtab[cnt].locrec_offset != 0)
+      {
+       assert (used < head->namehash_used);
+       names[used].name = tmpl_ah->addr + namehashtab[cnt].name_offset;
+       names[used++].locrec
+         = (struct locrecent *) ((char *) tmpl_ah->addr +
+                                 namehashtab[cnt].locrec_offset);
+      }
+
+  /* Sort the names.  */
+  qsort (names, used, sizeof (struct nameent), nameentcmp);
+
+  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;
+      }
+
+  /* Sort by file locations.  */
+  qsort (files, sumused, sizeof (struct dataent), dataentcmp);
+
+  /* Open the archive.  This call never returns if we cannot
+     successfully open the archive.  */
+  open_archive (&ah, false);
+
+  if (primary != NULL)
+    {
+      for (cnt = 0; cnt < used; ++cnt)
+       if (strcmp (names[cnt].name, primary) == 0)
+         break;
+      if (cnt < used)
+       {
+         locale_data_t data;
+
+         compute_data (tmpl_ah, &names[cnt], sumused, files, data);
+         result |= add_locale_to_archive (&ah, primary, data, 0);
+         primary_locrec = names[cnt].locrec;
+         primary_nameent = &names[cnt];
+       }
+    }
+
+  for (cnt = 0; cnt < used; ++cnt)
+    if (&names[cnt] == primary_nameent)
+      continue;
+    else if ((cnt > 0 && names[cnt - 1].locrec == names[cnt].locrec)
+            || names[cnt].locrec == primary_locrec)
+      {
+       const char *oldname;
+       struct namehashent *namehashent;
+       uint32_t locrec_offset;
+
+       if (names[cnt].locrec == primary_locrec)
+         oldname = primary;
+       else
+         oldname = names[cnt - 1].name;
+       namehashent = insert_name (&ah, oldname, strlen (oldname), true);
+       assert (namehashent->name_offset != 0);
+       assert (namehashent->locrec_offset != 0);
+       locrec_offset = namehashent->locrec_offset;
+       add_alias (&ah, names[cnt].name, 0, oldname, &locrec_offset);
+      }
+    else
+      {
+       locale_data_t data;
+
+       compute_data (tmpl_ah, &names[cnt], sumused, files, data);
+       result |= add_locale_to_archive (&ah, names[cnt].name, data, 0);
+      }
+
+  while (nlist-- > 0)
+    {
+      const char *fname = *list++;
+      size_t fnamelen = strlen (fname);
+      struct stat64 st;
+      DIR *dirp;
+      struct dirent64 *d;
+      int seen;
+      locale_data_t data;
+      int cnt;
+
+      /* First see whether this really is a directory and whether it
+        contains all the require locale category files.  */
+      if (stat64 (fname, &st) < 0)
+       {
+         error (0, 0, "stat of \"%s\" failed: %s: ignored", fname,
+                strerror (errno));
+         continue;
+       }
+      if (!S_ISDIR (st.st_mode))
+       {
+         error (0, 0, "\"%s\" is no directory; ignored", fname);
+         continue;
+       }
+
+      dirp = opendir (fname);
+      if (dirp == NULL)
+       {
+         error (0, 0, "cannot open directory \"%s\": %s: ignored",
+                fname, strerror (errno));
+         continue;
+       }
+
+      seen = 0;
+      while ((d = readdir64 (dirp)) != NULL)
+       {
+         for (cnt = 0; cnt < __LC_LAST; ++cnt)
+           if (cnt != LC_ALL)
+             if (strcmp (d->d_name, locnames[cnt]) == 0)
+               {
+                 unsigned char d_type;
+
+                 /* We have an object of the required name.  If it's
+                    a directory we have to look at a file with the
+                    prefix "SYS_".  Otherwise we have found what we
+                    are looking for.  */
+#ifdef _DIRENT_HAVE_D_TYPE
+                 d_type = d->d_type;
+
+                 if (d_type != DT_REG)
+#endif
+                   {
+                     char fullname[fnamelen + 2 * strlen (d->d_name) + 7];
+
+#ifdef _DIRENT_HAVE_D_TYPE
+                     if (d_type == DT_UNKNOWN)
+#endif
+                       {
+                         strcpy (stpcpy (stpcpy (fullname, fname), "/"),
+                                 d->d_name);
+
+                         if (stat64 (fullname, &st) == -1)
+                           /* We cannot stat the file, ignore it.  */
+                           break;
+
+                         d_type = IFTODT (st.st_mode);
+                       }
+
+                     if (d_type == DT_DIR)
+                       {
+                         /* We have to do more tests.  The file is a
+                            directory and it therefore must contain a
+                            regular file with the same name except a
+                            "SYS_" prefix.  */
+                         char *t = stpcpy (stpcpy (fullname, fname), "/");
+                         strcpy (stpcpy (stpcpy (t, d->d_name), "/SYS_"),
+                                 d->d_name);
+
+                         if (stat64 (fullname, &st) == -1)
+                           /* There is no SYS_* file or we cannot
+                              access it.  */
+                           break;
+
+                         d_type = IFTODT (st.st_mode);
+                       }
+                   }
+
+                 /* If we found a regular file (eventually after
+                    following a symlink) we are successful.  */
+                 if (d_type == DT_REG)
+                   ++seen;
+                 break;
+               }
+       }
+
+      closedir (dirp);
+
+      if (seen != __LC_LAST - 1)
+       {
+         /* We don't have all locale category files.  Ignore the name.  */
+         error (0, 0, "incomplete set of locale files in \"%s\"",
+                fname);
+         continue;
+       }
+
+      /* Add the files to the archive.  To do this we first compute
+        sizes and the MD5 sums of all the files.  */
+      for (cnt = 0; cnt < __LC_LAST; ++cnt)
+       if (cnt != LC_ALL)
+         {
+           char fullname[fnamelen + 2 * strlen (locnames[cnt]) + 7];
+           int fd;
+
+           strcpy (stpcpy (stpcpy (fullname, fname), "/"), locnames[cnt]);
+           fd = open64 (fullname, O_RDONLY);
+           if (fd == -1 || fstat64 (fd, &st) == -1)
+             {
+               /* Cannot read the file.  */
+               if (fd != -1)
+                 close (fd);
+               break;
+             }
+
+           if (S_ISDIR (st.st_mode))
+             {
+               char *t;
+               close (fd);
+               t = stpcpy (stpcpy (fullname, fname), "/");
+               strcpy (stpcpy (stpcpy (t, locnames[cnt]), "/SYS_"),
+                       locnames[cnt]);
+
+               fd = open64 (fullname, O_RDONLY);
+               if (fd == -1 || fstat64 (fd, &st) == -1
+                   || !S_ISREG (st.st_mode))
+                 {
+                   if (fd != -1)
+                     close (fd);
+                   break;
+                 }
+             }
+
+           /* Map the file.  */
+           data[cnt].addr = mmap64 (NULL, st.st_size, PROT_READ, MAP_SHARED,
+                                    fd, 0);
+           if (data[cnt].addr == MAP_FAILED)
+             {
+               /* Cannot map it.  */
+               close (fd);
+               break;
+             }
+
+           data[cnt].size = st.st_size;
+           __md5_buffer (data[cnt].addr, st.st_size, data[cnt].sum);
+
+           /* We don't need the file descriptor anymore.  */
+           close (fd);
+         }
+
+      if (cnt != __LC_LAST)
+       {
+         while (cnt-- > 0)
+           if (cnt != LC_ALL)
+             munmap (data[cnt].addr, data[cnt].size);
+
+         error (0, 0, "cannot read all files in \"%s\": ignored", fname);
+
+         continue;
+       }
+
+      result |= add_locale_to_archive (&ah, basename (fname), data, 0);
+
+      for (cnt = 0; cnt < __LC_LAST; ++cnt)
+       if (cnt != LC_ALL)
+         munmap (data[cnt].addr, data[cnt].size);
+    }
+
+  /* We are done.  */
+  close_archive (&ah);
+
+  return result;
+}
 
 int main ()
 {
@@ -82,12 +538,16 @@ int main ()
   struct stat64 st;
   char *list[16384], *primary;
   unsigned int cnt = 0;
+  struct locarhandle tmpl_ah;
+  size_t loc_path_len = strlen (loc_path);
 
-  unlink (locar_file);
   dirp = opendir (loc_path);
   if (dirp == NULL)
     error (EXIT_FAILURE, errno, "cannot open directory \"%s\"", loc_path);
 
+  open_tmpl_archive (&tmpl_ah);
+
+  unlink (locar_file);
   primary = getenv ("LC_ALL");
   if (primary == NULL)
     primary = getenv ("LANG");
@@ -113,30 +573,25 @@ int main ()
              primary = ptr;
            }
          else
-           primary = ".....";
-       }
-      strcpy (stpcpy (path, loc_path), primary);
-      if (stat64 (path, &st) >= 0 && S_ISDIR (st.st_mode))
-       {
-          list[cnt] = strdup (path);
-          if (list[cnt] == NULL)
-           error (0, errno, "cannot add file to list \"%s\"", path);
-         else
-           cnt++;
+           primary = NULL;
        }
-      if (cnt == 0)
-       primary = NULL;
     }
 
+  memcpy (path, loc_path, loc_path_len);
+
   while ((d = readdir64 (dirp)) != NULL)
     {
       if (strcmp (d->d_name, ".") == 0 || strcmp (d->d_name, "..") == 0)
        continue;
 
-      if (primary && strcmp (d->d_name, primary) == 0)
-       continue;
+      size_t d_name_len = strlen (d->d_name);
+      if (loc_path_len + d_name_len + 1 > sizeof (path))
+       {
+         error (0, 0, "too long filename \"%s\"", d->d_name);
+         continue;
+       }
 
-      strcpy (stpcpy (path, loc_path), d->d_name);
+      memcpy (path + loc_path_len, d->d_name, d_name_len + 1);
       if (stat64 (path, &st) < 0)
        {
          error (0, errno, "cannot stat \"%s\"", path);
@@ -152,10 +607,18 @@ int main ()
          error (0, errno, "cannot add file to list \"%s\"", path);
          continue;
        }
+      if (primary != NULL && cnt > 0 && strcmp (primary, d->d_name) == 0)
+       {
+         char *p = list[0];
+         list[0] = list[cnt];
+         list[cnt] = p;
+       }
       cnt++;
     }
   closedir (dirp);
-  add_locales_to_archive (cnt, list, 0);
+  fill_archive (&tmpl_ah, cnt, list, primary);
+  close_archive (&tmpl_ah);
+  unlink (tmpl_file);
   char *argv[] = { "/usr/sbin/tzdata-update", NULL };
   execve (argv[0], (char *const *)argv, (char *const *)&argv[1]);
   exit (0);
index 779c17e..a8b70f8 100644 (file)
@@ -1,4 +1,4 @@
-%define glibcrelease 20
+%define glibcrelease 21
 %define auxarches i586 i686 athlon sparcv9 alphaev6
 %define xenarches i686 athlon
 %ifarch %{xenarches}
@@ -969,11 +969,6 @@ popd
 cd ..
 %endif
 
-# compatibility hack: this locale has vanished from glibc, but some other
-# programs are still using it. Normally we would handle it in the %pre
-# section but with glibc that is simply not an option
-mkdir -p $RPM_BUILD_ROOT%{_prefix}/lib/locale/ru_RU/LC_MESSAGES
-
 # Remove the files we don't want to distribute
 rm -f $RPM_BUILD_ROOT%{_prefix}/%{_lib}/libNoVersion*
 rm -f $RPM_BUILD_ROOT/%{_lib}/libNoVersion*
@@ -1051,7 +1046,19 @@ rm -f $RPM_BUILD_ROOT%{_prefix}/include/rpcsvc/rquota.[hx]
 # Hardlink identical locale files together
 %ifnarch %{auxarches}
 gcc -O2 -o build-%{nptl_target_cpu}-linuxnptl/hardlink fedora/hardlink.c
-build-%{nptl_target_cpu}-linuxnptl/hardlink -vc $RPM_BUILD_ROOT%{_prefix}/lib/locale
+rm ${RPM_BUILD_ROOT}${_prefix}/lib/locale/locale-archive || :
+olddir=`pwd`
+pushd ${RPM_BUILD_ROOT}${_prefix}/lib/locale
+# Intentionally we do not pass --alias-file=, aliases will be added
+# by build-locale-archive.
+$olddir/build-%{nptl_target_cpu}-linuxnptl/elf/ld.so \
+  --library-path $olddir/build-%{nptl_target_cpu}-linuxnptl/ \
+  $olddir/build-%{nptl_target_cpu}-linuxnptl/locale/localedef \
+    --prefix ${RPM_BUILD_ROOT} --add-to-archive \
+    *_*
+rm -rf *_*
+popd
+#build-%{nptl_target_cpu}-linuxnptl/hardlink -vc $RPM_BUILD_ROOT%{_prefix}/lib/locale
 %endif
 
 rm -f ${RPM_BUILD_ROOT}/%{_lib}/libnss1-*
@@ -1125,7 +1132,7 @@ grep -v '%{_prefix}/%{_lib}/lib.*\.a' < rpm.filelist.full |
        grep -v 'nscd' > rpm.filelist
 
 grep '%{_prefix}/bin' < rpm.filelist >> common.filelist
-grep '%{_prefix}/lib/locale' < rpm.filelist >> common.filelist
+grep '%{_prefix}/lib/locale' < rpm.filelist | grep -v /locale-archive.tmpl >> common.filelist
 grep '%{_prefix}/libexec/pt_chown' < rpm.filelist >> common.filelist
 grep '%{_prefix}/sbin/[^gi]' < rpm.filelist >> common.filelist
 grep '%{_prefix}/share' < rpm.filelist \
@@ -1495,6 +1502,7 @@ rm -f *.filelist*
 %ifnarch %{auxarches}
 %files -f common.filelist common
 %defattr(-,root,root)
+%attr(0644,root,root) %config(missingok) %{_prefix}/lib/locale/locale-archive.tmpl
 %attr(0644,root,root) %verify(not md5 size mtime mode) %ghost %config(missingok,noreplace) %{_prefix}/lib/locale/locale-archive
 %dir %attr(755,root,root) /etc/default
 %verify(not md5 size mtime) %config(noreplace) /etc/default/nss
@@ -1549,10 +1557,21 @@ rm -f *.filelist*
 %endif
 
 %changelog
+* Mon Apr 16 2007 Jakub Jelinek <jakub@redhat.com> 2.5.90-21
+- don't include individual locale files in glibc-common,
+  rather include prepared locale-archive template and let
+  build-locale-archive create locale-archive from the template
+  and any user supplied /usr/lib/locale/*_* directories,
+  then unlink the locale-archive template - this should save
+  > 80MB of glibc-common occupied disk space
+
 * Sat Mar 31 2007 Jakub Jelinek <jakub@redhat.com> 2.5.90-20
 - assorted NIS+ speedups (#223467)
 - fix HAVE_LIBCAP configure detection (#178934)
 - remove %{_prefix}/sbin/rpcinfo from glibc-common (#228894)
+- nexttoward*/nextafter* fixes (BZ#3306)
+- feholdexcept/feupdateenv fixes (BZ#3427)
+- speed up fnmatch with two or more * in the pattern
 
 * Sat Mar 17 2007 Jakub Jelinek <jakub@redhat.com> 2.5.90-19
 - fix power6 libm compat symbols on ppc32 (#232633)
index 5c0d5f1..201700d 100644 (file)
@@ -521,7 +521,7 @@ close_archive (struct locarhandle *ah)
 #include "../../intl/explodename.c"
 #include "../../intl/l10nflist.c"
 
-static struct namehashent *
+struct namehashent *
 insert_name (struct locarhandle *ah,
             const char *name, size_t name_len, bool replace)
 {
@@ -579,7 +579,7 @@ insert_name (struct locarhandle *ah,
   return &namehashtab[idx];
 }
 
-static void
+void
 add_alias (struct locarhandle *ah, const char *alias, bool replace,
           const char *oldname, uint32_t *locrec_offset_p)
 {