intl/icu/source/common/umapfile.c

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

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

mercurial