Print this page
2964 need POSIX 2008 locale object support
Reviewed by: Robert Mustacchi <rm@joyent.com>
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
Approved by: TBD

@@ -1,6 +1,7 @@
 /*
+ * Copyright 2014 Garrett D'Amore <garrett@damore.org>
  * Copyright 2010 Nexenta Systems, Inc.  All rights reserved.
  * Copyright (c) 1993
  *      The Regents of the University of California.  All rights reserved.
  *
  * This code is derived from software contributed to Berkeley by

@@ -37,18 +38,20 @@
 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <unistd.h>
 
+#include "libc.h"
 #include "runetype.h"
 #include "runefile.h"
 
-_RuneLocale *_Read_RuneMagi(FILE *);
-
 _RuneLocale *
-_Read_RuneMagi(FILE *fp)
+_Read_RuneMagi(const char *fname)
 {
         char *fdata, *data;
         void *lastp;
         _FileRuneLocale *frl;
         _RuneLocale *rl;

@@ -59,71 +62,62 @@
         void *variable;
         _FileRuneEntry *runetype_ext_ranges;
         _FileRuneEntry *maplower_ext_ranges;
         _FileRuneEntry *mapupper_ext_ranges;
         int runetype_ext_len = 0;
+        int fd;
 
-        if (fstat(fileno(fp), &sb) < 0)
+        if ((fd = open(fname, O_RDONLY)) < 0) {
+                errno = EINVAL;
                 return (NULL);
+        }
 
-        if ((size_t)sb.st_size < sizeof (_FileRuneLocale)) {
+        if (fstat(fd, &sb) < 0) {
+                (void) close(fd);
                 errno = EINVAL;
                 return (NULL);
         }
 
-        if ((fdata = malloc(sb.st_size)) == NULL)
+        if ((size_t)sb.st_size < sizeof (_FileRuneLocale)) {
+                (void) close(fd);
+                errno = EINVAL;
                 return (NULL);
-
-        errno = 0;
-        rewind(fp); /* Someone might have read the magic number once already */
-        if (errno) {
-                saverr = errno;
-                free(fdata);
-                errno = saverr;
-                return (NULL);
         }
 
-        if (fread(fdata, sb.st_size, 1, fp) != 1) {
-                saverr = errno;
-                free(fdata);
-                errno = saverr;
+
+        fdata = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
+        (void) close(fd);
+        if (fdata == NULL) {
+                errno = EINVAL;
                 return (NULL);
         }
 
         frl = (_FileRuneLocale *)(void *)fdata;
         lastp = fdata + sb.st_size;
 
         variable = frl + 1;
 
         if (memcmp(frl->magic, _FILE_RUNE_MAGIC_1, sizeof (frl->magic))) {
-                free(fdata);
-                errno = EINVAL;
-                return (NULL);
+                goto invalid;
         }
 
         runetype_ext_ranges = (_FileRuneEntry *)variable;
         variable = runetype_ext_ranges + frl->runetype_ext_nranges;
         if (variable > lastp) {
-                free(fdata);
-                errno = EINVAL;
-                return (NULL);
+                goto invalid;
         }
 
         maplower_ext_ranges = (_FileRuneEntry *)variable;
         variable = maplower_ext_ranges + frl->maplower_ext_nranges;
         if (variable > lastp) {
-                free(fdata);
-                errno = EINVAL;
-                return (NULL);
+                goto invalid;
         }
 
         mapupper_ext_ranges = (_FileRuneEntry *)variable;
         variable = mapupper_ext_ranges + frl->mapupper_ext_nranges;
         if (variable > lastp) {
-                free(fdata);
-                errno = EINVAL;
-                return (NULL);
+                goto invalid;
         }
 
         frr = runetype_ext_ranges;
         for (x = 0; x < frl->runetype_ext_nranges; ++x) {
                 uint32_t *types;

@@ -132,34 +126,30 @@
                         int len = frr[x].max - frr[x].min + 1;
                         types = variable;
                         variable = types + len;
                         runetype_ext_len += len;
                         if (variable > lastp) {
-                                free(fdata);
-                                errno = EINVAL;
-                                return (NULL);
+                                goto invalid;
                         }
                 }
         }
 
         if ((char *)variable + frl->variable_len > (char *)lastp) {
-                free(fdata);
-                errno = EINVAL;
-                return (NULL);
+                goto invalid;
         }
 
         /*
          * Convert from disk format to host format.
          */
-        data = malloc(sizeof (_RuneLocale) +
+        data = libc_malloc(sizeof (_RuneLocale) +
             (frl->runetype_ext_nranges + frl->maplower_ext_nranges +
             frl->mapupper_ext_nranges) * sizeof (_RuneEntry) +
             runetype_ext_len * sizeof (*rr->__types) +
             frl->variable_len);
         if (data == NULL) {
                 saverr = errno;
-                free(fdata);
+                (void) munmap(fdata, sb.st_size);
                 errno = saverr;
                 return (NULL);
         }
 
         rl = (_RuneLocale *)(void *)data;

@@ -227,11 +217,11 @@
                 rr[x].__max = frr[x].max;
                 rr[x].__map = frr[x].map;
         }
 
         (void) memcpy(rl->__variable, variable, rl->__variable_len);
-        free(fdata);
+        (void) munmap(fdata, sb.st_size);
 
         /*
          * Go out and zero pointers that should be zero.
          */
         if (!rl->__variable_len)

@@ -245,6 +235,11 @@
 
         if (!rl->__mapupper_ext.__nranges)
                 rl->__mapupper_ext.__ranges = NULL;
 
         return (rl);
+
+invalid:
+        (void) munmap(fdata, sb.st_size);
+        errno = EINVAL;
+        return (NULL);
 }