intl/icu/source/common/umapfile.c

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /*
     2 ******************************************************************************
     3 *
     4 *   Copyright (C) 1999-2013, International Business Machines
     5 *   Corporation and others.  All Rights Reserved.
     6 *
     7 ******************************************************************************/
    10 /*----------------------------------------------------------------------------
    11  *
    12  *       Memory mapped file wrappers for use by the ICU Data Implementation
    13  *       All of the platform-specific implementation for mapping data files
    14  *         is here.  The rest of the ICU Data implementation uses only the
    15  *         wrapper functions.
    16  *
    17  *----------------------------------------------------------------------------*/
    18 /* Defines _XOPEN_SOURCE for access to POSIX functions.
    19  * Must be before any other #includes. */
    20 #include "uposixdefs.h"
    22 #include "unicode/putil.h"
    23 #include "udatamem.h"
    24 #include "umapfile.h"
    26 /* memory-mapping base definitions ------------------------------------------ */
    28 #if MAP_IMPLEMENTATION==MAP_WIN32
    29 #   define WIN32_LEAN_AND_MEAN
    30 #   define VC_EXTRALEAN
    31 #   define NOUSER
    32 #   define NOSERVICE
    33 #   define NOIME
    34 #   define NOMCX
    35 #   include <windows.h>
    36 #   include "cmemory.h"
    38     typedef HANDLE MemoryMap;
    40 #   define IS_MAP(map) ((map)!=NULL)
    41 #elif MAP_IMPLEMENTATION==MAP_POSIX || MAP_IMPLEMENTATION==MAP_390DLL
    42     typedef size_t MemoryMap;
    44 #   define IS_MAP(map) ((map)!=0)
    46 #   include <unistd.h>
    47 #   include <sys/mman.h>
    48 #   include <sys/stat.h>
    49 #   include <fcntl.h>
    51 #   ifndef MAP_FAILED
    52 #       define MAP_FAILED ((void*)-1)
    53 #   endif
    55 #   if MAP_IMPLEMENTATION==MAP_390DLL
    56         /*   No memory mapping for 390 batch mode.  Fake it using dll loading.  */
    57 #       include <dll.h>
    58 #       include "cstring.h"
    59 #       include "cmemory.h"
    60 #       include "unicode/udata.h"
    61 #       define LIB_PREFIX "lib"
    62 #       define LIB_SUFFIX ".dll"
    63         /* This is inconvienient until we figure out what to do with U_ICUDATA_NAME in utypes.h */
    64 #       define U_ICUDATA_ENTRY_NAME "icudt" U_ICU_VERSION_SHORT U_LIB_SUFFIX_C_NAME_STRING "_dat"
    65 #   endif
    66 #elif MAP_IMPLEMENTATION==MAP_STDIO
    67 #   include <stdio.h>
    68 #   include "cmemory.h"
    70     typedef void *MemoryMap;
    72 #   define IS_MAP(map) ((map)!=NULL)
    73 #endif
    75 /*----------------------------------------------------------------------------*
    76  *                                                                            *
    77  *   Memory Mapped File support.  Platform dependent implementation of        *
    78  *                           functions used by the rest of the implementation.*
    79  *                                                                            *
    80  *----------------------------------------------------------------------------*/
    81 #if MAP_IMPLEMENTATION==MAP_NONE
    82     U_CFUNC UBool
    83     uprv_mapFile(UDataMemory *pData, const char *path) {
    84         UDataMemory_init(pData); /* Clear the output struct. */
    85         return FALSE;            /* no file access */
    86     }
    88     U_CFUNC void uprv_unmapFile(UDataMemory *pData) {
    89         /* nothing to do */
    90     }
    91 #elif MAP_IMPLEMENTATION==MAP_WIN32
    92     U_CFUNC UBool
    93     uprv_mapFile(
    94          UDataMemory *pData,    /* Fill in with info on the result doing the mapping. */
    95                                 /*   Output only; any original contents are cleared.  */
    96          const char *path       /* File path to be opened/mapped                      */
    97          )
    98     {
    99         HANDLE map;
   100         HANDLE file;
   101         SECURITY_ATTRIBUTES mappingAttributes;
   102         SECURITY_ATTRIBUTES *mappingAttributesPtr = NULL;
   103         SECURITY_DESCRIPTOR securityDesc;
   105         UDataMemory_init(pData); /* Clear the output struct.        */
   107         /* open the input file */
   108         file=CreateFileA(path, GENERIC_READ, FILE_SHARE_READ, NULL,
   109             OPEN_EXISTING,
   110             FILE_ATTRIBUTE_NORMAL|FILE_FLAG_RANDOM_ACCESS, NULL);
   111         if(file==INVALID_HANDLE_VALUE) {
   112             return FALSE;
   113         }
   115         /* Declare and initialize a security descriptor.
   116            This is required for multiuser systems on Windows 2000 SP4 and beyond */
   117         if (InitializeSecurityDescriptor(&securityDesc, SECURITY_DESCRIPTOR_REVISION)) {
   118             /* give the security descriptor a Null Dacl done using the  "TRUE, (PACL)NULL" here	*/
   119             if (SetSecurityDescriptorDacl(&securityDesc, TRUE, (PACL)NULL, FALSE)) {
   120                 /* Make the security attributes point to the security descriptor */
   121                 uprv_memset(&mappingAttributes, 0, sizeof(mappingAttributes));
   122                 mappingAttributes.nLength = sizeof(mappingAttributes);
   123                 mappingAttributes.lpSecurityDescriptor = &securityDesc;
   124                 mappingAttributes.bInheritHandle = FALSE; /* object uninheritable */
   125                 mappingAttributesPtr = &mappingAttributes;
   126             }
   127         }
   128         /* else creating security descriptors can fail when we are on Windows 98,
   129            and mappingAttributesPtr == NULL for that case. */
   131         /* create an unnamed Windows file-mapping object for the specified file */
   132         map=CreateFileMapping(file, mappingAttributesPtr, PAGE_READONLY, 0, 0, NULL);
   133         CloseHandle(file);
   134         if(map==NULL) {
   135             return FALSE;
   136         }
   138         /* map a view of the file into our address space */
   139         pData->pHeader=(const DataHeader *)MapViewOfFile(map, FILE_MAP_READ, 0, 0, 0);
   140         if(pData->pHeader==NULL) {
   141             CloseHandle(map);
   142             return FALSE;
   143         }
   144         pData->map=map;
   145         return TRUE;
   146     }
   148     U_CFUNC void
   149     uprv_unmapFile(UDataMemory *pData) {
   150         if(pData!=NULL && pData->map!=NULL) {
   151             UnmapViewOfFile(pData->pHeader);
   152             CloseHandle(pData->map);
   153             pData->pHeader=NULL;
   154             pData->map=NULL;
   155         }
   156     }
   160 #elif MAP_IMPLEMENTATION==MAP_POSIX
   161     U_CFUNC UBool
   162     uprv_mapFile(UDataMemory *pData, const char *path) {
   163         int fd;
   164         int length;
   165         struct stat mystat;
   166         void *data;
   168         UDataMemory_init(pData); /* Clear the output struct.        */
   170         /* determine the length of the file */
   171         if(stat(path, &mystat)!=0 || mystat.st_size<=0) {
   172             return FALSE;
   173         }
   174         length=mystat.st_size;
   176         /* open the file */
   177         fd=open(path, O_RDONLY);
   178         if(fd==-1) {
   179             return FALSE;
   180         }
   182         /* get a view of the mapping */
   183 #if U_PLATFORM != U_PF_HPUX
   184         data=mmap(0, length, PROT_READ, MAP_SHARED,  fd, 0);
   185 #else
   186         data=mmap(0, length, PROT_READ, MAP_PRIVATE, fd, 0);
   187 #endif
   188         close(fd); /* no longer needed */
   189         if(data==MAP_FAILED) {
   190             return FALSE;
   191         }
   193         pData->map = (char *)data + length;
   194         pData->pHeader=(const DataHeader *)data;
   195         pData->mapAddr = data;
   196 #if U_PLATFORM == U_PF_IPHONE
   197         posix_madvise(data, length, POSIX_MADV_RANDOM);
   198 #endif
   199         return TRUE;
   200     }
   202     U_CFUNC void
   203     uprv_unmapFile(UDataMemory *pData) {
   204         if(pData!=NULL && pData->map!=NULL) {
   205             size_t dataLen = (char *)pData->map - (char *)pData->mapAddr;
   206             if(munmap(pData->mapAddr, dataLen)==-1) {
   207             }
   208             pData->pHeader=NULL;
   209             pData->map=0;
   210             pData->mapAddr=NULL;
   211         }
   212     }
   216 #elif MAP_IMPLEMENTATION==MAP_STDIO
   217     /* copy of the filestrm.c/T_FileStream_size() implementation */
   218     static int32_t
   219     umap_fsize(FILE *f) {
   220         int32_t savedPos = ftell(f);
   221         int32_t size = 0;
   223         /*Changes by Bertrand A. D. doesn't affect the current position
   224         goes to the end of the file before ftell*/
   225         fseek(f, 0, SEEK_END);
   226         size = (int32_t)ftell(f);
   227         fseek(f, savedPos, SEEK_SET);
   228         return size;
   229     }
   231     U_CFUNC UBool
   232     uprv_mapFile(UDataMemory *pData, const char *path) {
   233         FILE *file;
   234         int32_t fileLength;
   235         void *p;
   237         UDataMemory_init(pData); /* Clear the output struct.        */
   238         /* open the input file */
   239         file=fopen(path, "rb");
   240         if(file==NULL) {
   241             return FALSE;
   242         }
   244         /* get the file length */
   245         fileLength=umap_fsize(file);
   246         if(ferror(file) || fileLength<=20) {
   247             fclose(file);
   248             return FALSE;
   249         }
   251         /* allocate the memory to hold the file data */
   252         p=uprv_malloc(fileLength);
   253         if(p==NULL) {
   254             fclose(file);
   255             return FALSE;
   256         }
   258         /* read the file */
   259         if(fileLength!=fread(p, 1, fileLength, file)) {
   260             uprv_free(p);
   261             fclose(file);
   262             return FALSE;
   263         }
   265         fclose(file);
   266         pData->map=p;
   267         pData->pHeader=(const DataHeader *)p;
   268         pData->mapAddr=p;
   269         return TRUE;
   270     }
   272     U_CFUNC void
   273     uprv_unmapFile(UDataMemory *pData) {
   274         if(pData!=NULL && pData->map!=NULL) {
   275             uprv_free(pData->map);
   276             pData->map     = NULL;
   277             pData->mapAddr = NULL;
   278             pData->pHeader = NULL;
   279         }
   280     }
   283 #elif MAP_IMPLEMENTATION==MAP_390DLL
   284     /*  390 specific Library Loading.
   285      *  This is the only platform left that dynamically loads an ICU Data Library.
   286      *  All other platforms use .data files when dynamic loading is required, but
   287      *  this turn out to be awkward to support in 390 batch mode.
   288      *
   289      *  The idea here is to hide the fact that 390 is using dll loading from the
   290      *   rest of ICU, and make it look like there is file loading happening.
   291      *
   292      */
   294     static char *strcpy_returnEnd(char *dest, const char *src)
   295     {
   296         while((*dest=*src)!=0) {
   297             ++dest;
   298             ++src;
   299         }
   300         return dest;
   301     }
   303     /*------------------------------------------------------------------------------
   304      *                                                                              
   305      *  computeDirPath   given a user-supplied path of an item to be opened,             
   306      *                         compute and return 
   307      *                            - the full directory path to be used 
   308      *                              when opening the file.
   309      *                            - Pointer to null at end of above returned path    
   310      *
   311      *                       Parameters:
   312      *                          path:        input path.  Buffer is not altered.
   313      *                          pathBuffer:  Output buffer.  Any contents are overwritten.
   314      *
   315      *                       Returns:
   316      *                          Pointer to null termination in returned pathBuffer.
   317      *
   318      *                    TODO:  This works the way ICU historically has, but the
   319      *                           whole data fallback search path is so complicated that
   320      *                           proabably almost no one will ever really understand it,
   321      *                           the potential for confusion is large.  (It's not just 
   322      *                           this one function, but the whole scheme.)
   323      *                            
   324      *------------------------------------------------------------------------------*/
   325     static char *uprv_computeDirPath(const char *path, char *pathBuffer)
   326     {
   327         char   *finalSlash;       /* Ptr to last dir separator in input path, or null if none. */
   328         int32_t pathLen;          /* Length of the returned directory path                     */
   330         finalSlash = 0;
   331         if (path != 0) {
   332             finalSlash = uprv_strrchr(path, U_FILE_SEP_CHAR);
   333         }
   335         *pathBuffer = 0;
   336         if (finalSlash == 0) {
   337         /* No user-supplied path.  
   338             * Copy the ICU_DATA path to the path buffer and return that*/
   339             const char *icuDataDir;
   340             icuDataDir=u_getDataDirectory();
   341             if(icuDataDir!=NULL && *icuDataDir!=0) {
   342                 return strcpy_returnEnd(pathBuffer, icuDataDir);
   343             } else {
   344                 /* there is no icuDataDir either.  Just return the empty pathBuffer. */
   345                 return pathBuffer;
   346             }
   347         } 
   349         /* User supplied path did contain a directory portion.
   350         * Copy it to the output path buffer */
   351         pathLen = (int32_t)(finalSlash - path + 1);
   352         uprv_memcpy(pathBuffer, path, pathLen);
   353         *(pathBuffer+pathLen) = 0;
   354         return pathBuffer+pathLen;
   355     }
   358 #   define DATA_TYPE "dat"
   360     U_CFUNC UBool uprv_mapFile(UDataMemory *pData, const char *path) {
   361         const char *inBasename;
   362         char *basename;
   363         char pathBuffer[1024];
   364         const DataHeader *pHeader;
   365         dllhandle *handle;
   366         void *val=0;
   368         inBasename=uprv_strrchr(path, U_FILE_SEP_CHAR);
   369         if(inBasename==NULL) {
   370             inBasename = path;
   371         } else {
   372             inBasename++;
   373         }
   374         basename=uprv_computeDirPath(path, pathBuffer);
   375         if(uprv_strcmp(inBasename, U_ICUDATA_NAME".dat") != 0) {
   376             /* must mmap file... for build */
   377             int fd;
   378             int length;
   379             struct stat mystat;
   380             void *data;
   381             UDataMemory_init(pData); /* Clear the output struct. */
   383             /* determine the length of the file */
   384             if(stat(path, &mystat)!=0 || mystat.st_size<=0) {
   385                 return FALSE;
   386             }
   387             length=mystat.st_size;
   389             /* open the file */
   390             fd=open(path, O_RDONLY);
   391             if(fd==-1) {
   392                 return FALSE;
   393             }
   395             /* get a view of the mapping */
   396             data=mmap(0, length, PROT_READ, MAP_PRIVATE, fd, 0);
   397             close(fd); /* no longer needed */
   398             if(data==MAP_FAILED) {
   399                 return FALSE;
   400             }
   401             pData->map = (char *)data + length;
   402             pData->pHeader=(const DataHeader *)data;
   403             pData->mapAddr = data;
   404             return TRUE;
   405         }
   407 #       ifdef OS390BATCH
   408             /* ### hack: we still need to get u_getDataDirectory() fixed
   409             for OS/390 (batch mode - always return "//"? )
   410             and this here straightened out with LIB_PREFIX and LIB_SUFFIX (both empty?!)
   411             This is probably due to the strange file system on OS/390.  It's more like
   412             a database with short entry names than a typical file system. */
   413             /* U_ICUDATA_NAME should always have the correct name */
   414             /* BUT FOR BATCH MODE IT IS AN EXCEPTION BECAUSE */
   415             /* THE FIRST THREE LETTERS ARE PREASSIGNED TO THE */
   416             /* PROJECT!!!!! */
   417             uprv_strcpy(pathBuffer, "IXMI" U_ICU_VERSION_SHORT "DA");
   418 #       else
   419             /* set up the library name */
   420             uprv_strcpy(basename, LIB_PREFIX U_LIBICUDATA_NAME U_ICU_VERSION_SHORT LIB_SUFFIX);
   421 #       endif
   423 #       ifdef UDATA_DEBUG
   424              fprintf(stderr, "dllload: %s ", pathBuffer);
   425 #       endif
   427         handle=dllload(pathBuffer);
   429 #       ifdef UDATA_DEBUG
   430                fprintf(stderr, " -> %08X\n", handle );
   431 #       endif
   433         if(handle != NULL) {
   434                /* we have a data DLL - what kind of lookup do we need here? */
   435                /* try to find the Table of Contents */
   436                UDataMemory_init(pData); /* Clear the output struct.        */
   437                val=dllqueryvar((dllhandle*)handle, U_ICUDATA_ENTRY_NAME);
   438                if(val == 0) {
   439                     /* failed... so keep looking */
   440                     return FALSE;
   441                }
   442 #              ifdef UDATA_DEBUG
   443                     fprintf(stderr, "dllqueryvar(%08X, %s) -> %08X\n", handle, U_ICUDATA_ENTRY_NAME, val);
   444 #              endif
   446                pData->pHeader=(const DataHeader *)val;
   447                return TRUE;
   448          } else {
   449                return FALSE; /* no handle */
   450          }
   451     }
   453     U_CFUNC void uprv_unmapFile(UDataMemory *pData) {
   454         if(pData!=NULL && pData->map!=NULL) {
   455             uprv_free(pData->map);
   456             pData->map     = NULL;
   457             pData->mapAddr = NULL;
   458             pData->pHeader = NULL;
   459         }   
   460     }
   462 #else
   463 #   error MAP_IMPLEMENTATION is set incorrectly
   464 #endif

mercurial