]> sourceware.org Git - glibc.git/commitdiff
2002-08-15 Roland McGrath <roland@redhat.com>
authorRoland McGrath <roland@gnu.org>
Thu, 15 Aug 2002 08:29:16 +0000 (08:29 +0000)
committerRoland McGrath <roland@gnu.org>
Thu, 15 Aug 2002 08:29:16 +0000 (08:29 +0000)
* locale/loadarchive.c (_nl_load_locale_from_archive): Don't read the
header separately, just map an initial window of 2MB from the file
and remap if that is not large enough to cover the whole header.

locale/loadarchive.c

index 59ac916e298b72247cb3acbe798c2824b508fb0d..845b9b077465215de6ee77942fb16322b9bde7bc 100644 (file)
 /* Name of the locale archive file.  */
 static const char archfname[] = LOCALEDIR "/locale-archive";
 
+/* Size of initial mapping window, optimal if large enough to
+   cover the header plus the initial locale.  */
+#define ARCHIVE_MAPPING_WINDOW (2 * 1024 * 1024)
+
 
 /* Record of contiguous pages already mapped from the locale archive.  */
 struct archmapped
@@ -174,6 +178,9 @@ _nl_load_locale_from_archive (int category, const char **namep)
   /* Make sure the archive is loaded.  */
   if (archmapped == NULL)
     {
+      void *result;
+      size_t headsize, mapsize;
+
       /* We do this early as a sign that we have tried to open the archive.
         If headmap.ptr remains null, that's an indication that we tried
         and failed, so we won't try again.  */
@@ -193,49 +200,48 @@ _nl_load_locale_from_archive (int category, const char **namep)
          return NULL;
        }
 
-      if (sizeof (void *) > 4)
-       {
-         /* We will just map the whole file, what the hell.  */
-         void *result = __mmap64 (NULL, archive_stat.st_size,
-                                  PROT_READ, MAP_SHARED, fd, 0);
-         if (result == MAP_FAILED)
-           goto close_and_out;
-         /* Check whether the file is large enough for the sizes given in the
-            header.  */
-         if (calculate_head_size ((const struct locarhead *) result)
-             > archive_stat.st_size)
-           {
-             (void) __munmap (result, archive_stat.st_size);
-             goto close_and_out;
-           }
-         __close (fd);
-         fd = -1;
 
-         headmap.ptr = result;
-         /* headmap.from already initialized to zero.  */
-         headmap.len = archive_stat.st_size;
-       }
-      else
-       {
-         struct locarhead head;
-         off_t head_size;
-         void *result;
+      /* Map an initial window probably large enough to cover the header
+        and the first locale's data.  With a large address space, we can
+        just map the whole file and be sure everything is covered.  */
 
-         if (TEMP_FAILURE_RETRY (__read (fd, &head, sizeof (head)))
-             != sizeof (head))
-           goto close_and_out;
-         head_size = calculate_head_size (&head);
-         if (head_size > archive_stat.st_size)
+      mapsize = (sizeof (void *) > 4 ? archive_stat.st_size
+                : MAX (archive_stat.st_size, ARCHIVE_MAPPING_WINDOW));
+
+      result = __mmap64 (NULL, mapsize, PROT_READ, MAP_SHARED, fd, 0);
+      if (result == MAP_FAILED)
+       goto close_and_out;
+
+      /* Check whether the file is large enough for the sizes given in
+        the header.  Theoretically an archive could be so large that
+        just the header fails to fit in our initial mapping window.  */
+      headsize = calculate_head_size ((const struct locarhead *) result);
+      if (headsize > mapsize)
+       {
+         (void) __munmap (result, mapsize);
+         if (sizeof (void *) > 4 || headsize > archive_stat.st_size)
+           /* The file is not big enough for the header.  Bogus.  */
            goto close_and_out;
-         result = __mmap64 (NULL, head_size, PROT_READ, MAP_SHARED, fd, 0);
+
+         /* Freakishly long header.  */
+         /* XXX could use mremap when available */
+         mapsize = (headsize + ps - 1) & ~(ps - 1);
+         result = __mmap64 (NULL, mapsize, PROT_READ, MAP_SHARED, fd, 0);
          if (result == MAP_FAILED)
            goto close_and_out;
+       }
 
-         /* Record that we have mapped the initial pages of the file.  */
-         headmap.ptr = result;
-         headmap.len = MIN ((head_size + ps - 1) & ~(ps - 1),
-                            archive_stat.st_size);
+      if (sizeof (void *) > 4 || mapsize >= archive_stat.st_size)
+       {
+         /* We've mapped the whole file already, so we can be
+            sure we won't need this file descriptor later.  */
+         __close (fd);
+         fd = -1;
        }
+
+      headmap.ptr = result;
+      /* headmap.from already initialized to zero.  */
+      headmap.len = mapsize;
     }
 
   /* If there is no archive or it cannot be loaded for some reason fail.  */
This page took 0.04538 seconds and 5 git commands to generate.