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,19 @@
#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 "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 +61,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,21 +125,17 @@
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.
*/
@@ -155,11 +144,11 @@
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 +216,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 +234,11 @@
if (!rl->__mapupper_ext.__nranges)
rl->__mapupper_ext.__ranges = NULL;
return (rl);
+
+invalid:
+ (void) munmap(fdata, sb.st_size);
+ errno = EINVAL;
+ return (NULL);
}