blob: 145582ea97acd46d187f240ee469441a0a27582e [file] [log] [blame]
Jungshik Shin87232d82017-05-13 21:10:13 -07001// © 2016 and later: Unicode, Inc. and others.
Jungshik Shin5feb9ad2016-10-21 12:52:48 -07002// License & terms of use: http://www.unicode.org/copyright.html
jshin@chromium.org6f31ac32014-03-26 22:15:14 +00003/*
4******************************************************************************
5*
6* Copyright (C) 1999-2013, International Business Machines
7* Corporation and others. All Rights Reserved.
8*
9******************************************************************************/
10
11
12/*----------------------------------------------------------------------------
13 *
14 * Memory mapped file wrappers for use by the ICU Data Implementation
15 * All of the platform-specific implementation for mapping data files
16 * is here. The rest of the ICU Data implementation uses only the
17 * wrapper functions.
18 *
19 *----------------------------------------------------------------------------*/
20/* Defines _XOPEN_SOURCE for access to POSIX functions.
21 * Must be before any other #includes. */
22#include "uposixdefs.h"
23
24#include "unicode/putil.h"
Jungshik Shin42d50272018-10-24 01:22:09 -070025#include "unicode/ustring.h"
jshin@chromium.org6f31ac32014-03-26 22:15:14 +000026#include "udatamem.h"
27#include "umapfile.h"
28
29/* memory-mapping base definitions ------------------------------------------ */
30
31#if MAP_IMPLEMENTATION==MAP_WIN32
Jungshik Shin87232d82017-05-13 21:10:13 -070032#ifndef WIN32_LEAN_AND_MEAN
jshin@chromium.org6f31ac32014-03-26 22:15:14 +000033# define WIN32_LEAN_AND_MEAN
Jungshik Shin87232d82017-05-13 21:10:13 -070034#endif
jshin@chromium.org6f31ac32014-03-26 22:15:14 +000035# define VC_EXTRALEAN
36# define NOUSER
37# define NOSERVICE
38# define NOIME
39# define NOMCX
Frank Tang69c72a62019-04-03 21:41:21 -070040
41# if U_PLATFORM_HAS_WINUWP_API == 1
42 // Some previous versions of the Windows 10 SDK don't expose various APIs for UWP applications
43 // to use, even though UWP apps are allowed to call and use them. Temporarily change the
44 // WINAPI family partition below to Desktop, so that function declarations are visible for UWP.
45# include <winapifamily.h>
46# if !(WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_SYSTEM))
47# pragma push_macro("WINAPI_PARTITION_DESKTOP")
48# undef WINAPI_PARTITION_DESKTOP
49# define WINAPI_PARTITION_DESKTOP 1
50# define CHANGED_WINAPI_PARTITION_DESKTOP_VALUE
51# endif
52# endif
53
jshin@chromium.org6f31ac32014-03-26 22:15:14 +000054# include <windows.h>
Frank Tang69c72a62019-04-03 21:41:21 -070055
56# if U_PLATFORM_HAS_WINUWP_API == 1 && defined(CHANGED_WINAPI_PARTITION_DESKTOP_VALUE)
57# pragma pop_macro("WINAPI_PARTITION_DESKTOP")
58# endif
59
jshin@chromium.org6f31ac32014-03-26 22:15:14 +000060# include "cmemory.h"
61
Frank Tang69c72a62019-04-03 21:41:21 -070062typedef HANDLE MemoryMap;
jshin@chromium.org6f31ac32014-03-26 22:15:14 +000063
Frank Tang69c72a62019-04-03 21:41:21 -070064# define IS_MAP(map) ((map)!=nullptr)
65
jshin@chromium.org6f31ac32014-03-26 22:15:14 +000066#elif MAP_IMPLEMENTATION==MAP_POSIX || MAP_IMPLEMENTATION==MAP_390DLL
67 typedef size_t MemoryMap;
68
69# define IS_MAP(map) ((map)!=0)
70
71# include <unistd.h>
72# include <sys/mman.h>
73# include <sys/stat.h>
74# include <fcntl.h>
75
76# ifndef MAP_FAILED
77# define MAP_FAILED ((void*)-1)
78# endif
79
80# if MAP_IMPLEMENTATION==MAP_390DLL
81 /* No memory mapping for 390 batch mode. Fake it using dll loading. */
82# include <dll.h>
83# include "cstring.h"
84# include "cmemory.h"
85# include "unicode/udata.h"
86# define LIB_PREFIX "lib"
87# define LIB_SUFFIX ".dll"
Jungshik Shin42d50272018-10-24 01:22:09 -070088 /* This is inconvenient until we figure out what to do with U_ICUDATA_NAME in utypes.h */
jshin@chromium.org6f31ac32014-03-26 22:15:14 +000089# define U_ICUDATA_ENTRY_NAME "icudt" U_ICU_VERSION_SHORT U_LIB_SUFFIX_C_NAME_STRING "_dat"
90# endif
91#elif MAP_IMPLEMENTATION==MAP_STDIO
92# include <stdio.h>
93# include "cmemory.h"
94
95 typedef void *MemoryMap;
96
Frank Tang69c72a62019-04-03 21:41:21 -070097# define IS_MAP(map) ((map)!=nullptr)
jshin@chromium.org6f31ac32014-03-26 22:15:14 +000098#endif
99
100/*----------------------------------------------------------------------------*
101 * *
102 * Memory Mapped File support. Platform dependent implementation of *
103 * functions used by the rest of the implementation.*
104 * *
105 *----------------------------------------------------------------------------*/
106#if MAP_IMPLEMENTATION==MAP_NONE
107 U_CFUNC UBool
Jungshik Shin42d50272018-10-24 01:22:09 -0700108 uprv_mapFile(UDataMemory *pData, const char *path, UErrorCode *status) {
109 if (U_FAILURE(*status)) {
Frank Tang1f164ee2022-11-08 12:31:27 -0800110 return false;
Jungshik Shin42d50272018-10-24 01:22:09 -0700111 }
jshin@chromium.org6f31ac32014-03-26 22:15:14 +0000112 UDataMemory_init(pData); /* Clear the output struct. */
Frank Tang1f164ee2022-11-08 12:31:27 -0800113 return false; /* no file access */
jshin@chromium.org6f31ac32014-03-26 22:15:14 +0000114 }
115
116 U_CFUNC void uprv_unmapFile(UDataMemory *pData) {
117 /* nothing to do */
118 }
119#elif MAP_IMPLEMENTATION==MAP_WIN32
120 U_CFUNC UBool
121 uprv_mapFile(
122 UDataMemory *pData, /* Fill in with info on the result doing the mapping. */
123 /* Output only; any original contents are cleared. */
Jungshik Shin42d50272018-10-24 01:22:09 -0700124 const char *path, /* File path to be opened/mapped. */
125 UErrorCode *status /* Error status, used to report out-of-memory errors. */
jshin@chromium.org6f31ac32014-03-26 22:15:14 +0000126 )
127 {
Jungshik Shin42d50272018-10-24 01:22:09 -0700128 if (U_FAILURE(*status)) {
Frank Tang1f164ee2022-11-08 12:31:27 -0800129 return false;
Jungshik Shin42d50272018-10-24 01:22:09 -0700130 }
131
Frank Tang69c72a62019-04-03 21:41:21 -0700132 HANDLE map = nullptr;
133 HANDLE file = INVALID_HANDLE_VALUE;
134
jshin@chromium.org6f31ac32014-03-26 22:15:14 +0000135 UDataMemory_init(pData); /* Clear the output struct. */
136
137 /* open the input file */
Jungshik Shin87232d82017-05-13 21:10:13 -0700138#if U_PLATFORM_HAS_WINUWP_API == 0
Frank Tang69c72a62019-04-03 21:41:21 -0700139 // Note: In the non-UWP code-path (ie: Win32), the value of the path variable might have come from
140 // the CRT 'getenv' function, and would be therefore be encoded in the default ANSI code page.
141 // This means that we can't call the *W version of API below, whereas in the UWP code-path
142 // there is no 'getenv' call, and thus the string will be only UTF-8/Invariant characters.
143 file=CreateFileA(path, GENERIC_READ, FILE_SHARE_READ, nullptr,
jshin@chromium.org6f31ac32014-03-26 22:15:14 +0000144 OPEN_EXISTING,
Frank Tang69c72a62019-04-03 21:41:21 -0700145 FILE_ATTRIBUTE_NORMAL|FILE_FLAG_RANDOM_ACCESS, nullptr);
Jungshik Shin87232d82017-05-13 21:10:13 -0700146#else
Jungshik Shin42d50272018-10-24 01:22:09 -0700147 // Convert from UTF-8 string to UTF-16 string.
148 wchar_t utf16Path[MAX_PATH];
149 int32_t pathUtf16Len = 0;
150 u_strFromUTF8(reinterpret_cast<UChar*>(utf16Path), static_cast<int32_t>(UPRV_LENGTHOF(utf16Path)), &pathUtf16Len, path, -1, status);
151
152 if (U_FAILURE(*status)) {
Frank Tang1f164ee2022-11-08 12:31:27 -0800153 return false;
Jungshik Shin87232d82017-05-13 21:10:13 -0700154 }
Jungshik Shin42d50272018-10-24 01:22:09 -0700155 if (*status == U_STRING_NOT_TERMINATED_WARNING) {
156 // Report back an error instead of a warning.
157 *status = U_BUFFER_OVERFLOW_ERROR;
Frank Tang1f164ee2022-11-08 12:31:27 -0800158 return false;
Jungshik Shin87232d82017-05-13 21:10:13 -0700159 }
160
Frank Tang69c72a62019-04-03 21:41:21 -0700161 file = CreateFileW(utf16Path, GENERIC_READ, FILE_SHARE_READ, nullptr,
162 OPEN_EXISTING,
163 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, nullptr);
Jungshik Shin87232d82017-05-13 21:10:13 -0700164#endif
Jungshik Shin42d50272018-10-24 01:22:09 -0700165 if (file == INVALID_HANDLE_VALUE) {
166 // If we failed to open the file due to an out-of-memory error, then we want
167 // to report that error back to the caller.
168 if (HRESULT_FROM_WIN32(GetLastError()) == E_OUTOFMEMORY) {
169 *status = U_MEMORY_ALLOCATION_ERROR;
170 }
Frank Tang1f164ee2022-11-08 12:31:27 -0800171 return false;
jshin@chromium.org6f31ac32014-03-26 22:15:14 +0000172 }
173
Frank Tang69c72a62019-04-03 21:41:21 -0700174 // Note: We use NULL/nullptr for lpAttributes parameter below.
175 // This means our handle cannot be inherited and we will get the default security descriptor.
jshin@chromium.org6f31ac32014-03-26 22:15:14 +0000176 /* create an unnamed Windows file-mapping object for the specified file */
Frank Tang69c72a62019-04-03 21:41:21 -0700177 map = CreateFileMappingW(file, nullptr, PAGE_READONLY, 0, 0, nullptr);
178
jshin@chromium.org6f31ac32014-03-26 22:15:14 +0000179 CloseHandle(file);
Frank Tang69c72a62019-04-03 21:41:21 -0700180 if (map == nullptr) {
Jungshik Shin42d50272018-10-24 01:22:09 -0700181 // If we failed to create the mapping due to an out-of-memory error, then
182 // we want to report that error back to the caller.
183 if (HRESULT_FROM_WIN32(GetLastError()) == E_OUTOFMEMORY) {
184 *status = U_MEMORY_ALLOCATION_ERROR;
185 }
Frank Tang1f164ee2022-11-08 12:31:27 -0800186 return false;
jshin@chromium.org6f31ac32014-03-26 22:15:14 +0000187 }
188
189 /* map a view of the file into our address space */
Frank Tang69c72a62019-04-03 21:41:21 -0700190 pData->pHeader = reinterpret_cast<const DataHeader *>(MapViewOfFile(map, FILE_MAP_READ, 0, 0, 0));
191 if (pData->pHeader == nullptr) {
jshin@chromium.org6f31ac32014-03-26 22:15:14 +0000192 CloseHandle(map);
Frank Tang1f164ee2022-11-08 12:31:27 -0800193 return false;
jshin@chromium.org6f31ac32014-03-26 22:15:14 +0000194 }
Frank Tang69c72a62019-04-03 21:41:21 -0700195 pData->map = map;
Frank Tang1f164ee2022-11-08 12:31:27 -0800196 return true;
jshin@chromium.org6f31ac32014-03-26 22:15:14 +0000197 }
198
199 U_CFUNC void
200 uprv_unmapFile(UDataMemory *pData) {
Frank Tang69c72a62019-04-03 21:41:21 -0700201 if (pData != nullptr && pData->map != nullptr) {
jshin@chromium.org6f31ac32014-03-26 22:15:14 +0000202 UnmapViewOfFile(pData->pHeader);
203 CloseHandle(pData->map);
Frank Tang69c72a62019-04-03 21:41:21 -0700204 pData->pHeader = nullptr;
205 pData->map = nullptr;
jshin@chromium.org6f31ac32014-03-26 22:15:14 +0000206 }
207 }
208
209
210
211#elif MAP_IMPLEMENTATION==MAP_POSIX
212 U_CFUNC UBool
Jungshik Shin42d50272018-10-24 01:22:09 -0700213 uprv_mapFile(UDataMemory *pData, const char *path, UErrorCode *status) {
jshin@chromium.org6f31ac32014-03-26 22:15:14 +0000214 int fd;
215 int length;
216 struct stat mystat;
217 void *data;
218
Jungshik Shin42d50272018-10-24 01:22:09 -0700219 if (U_FAILURE(*status)) {
Frank Tang1f164ee2022-11-08 12:31:27 -0800220 return false;
Jungshik Shin42d50272018-10-24 01:22:09 -0700221 }
222
jshin@chromium.org6f31ac32014-03-26 22:15:14 +0000223 UDataMemory_init(pData); /* Clear the output struct. */
224
225 /* determine the length of the file */
226 if(stat(path, &mystat)!=0 || mystat.st_size<=0) {
Frank Tang1f164ee2022-11-08 12:31:27 -0800227 return false;
jshin@chromium.org6f31ac32014-03-26 22:15:14 +0000228 }
229 length=mystat.st_size;
230
231 /* open the file */
232 fd=open(path, O_RDONLY);
233 if(fd==-1) {
Frank Tang1f164ee2022-11-08 12:31:27 -0800234 return false;
jshin@chromium.org6f31ac32014-03-26 22:15:14 +0000235 }
236
237 /* get a view of the mapping */
238#if U_PLATFORM != U_PF_HPUX
239 data=mmap(0, length, PROT_READ, MAP_SHARED, fd, 0);
240#else
241 data=mmap(0, length, PROT_READ, MAP_PRIVATE, fd, 0);
242#endif
243 close(fd); /* no longer needed */
244 if(data==MAP_FAILED) {
Jungshik Shin42d50272018-10-24 01:22:09 -0700245 // Possibly check the errno value for ENOMEM, and report U_MEMORY_ALLOCATION_ERROR?
Frank Tang1f164ee2022-11-08 12:31:27 -0800246 return false;
jshin@chromium.org6f31ac32014-03-26 22:15:14 +0000247 }
248
249 pData->map = (char *)data + length;
250 pData->pHeader=(const DataHeader *)data;
251 pData->mapAddr = data;
252#if U_PLATFORM == U_PF_IPHONE
253 posix_madvise(data, length, POSIX_MADV_RANDOM);
254#endif
Frank Tang1f164ee2022-11-08 12:31:27 -0800255 return true;
jshin@chromium.org6f31ac32014-03-26 22:15:14 +0000256 }
257
258 U_CFUNC void
259 uprv_unmapFile(UDataMemory *pData) {
Frank Tang69c72a62019-04-03 21:41:21 -0700260 if(pData!=nullptr && pData->map!=nullptr) {
jshin@chromium.org6f31ac32014-03-26 22:15:14 +0000261 size_t dataLen = (char *)pData->map - (char *)pData->mapAddr;
262 if(munmap(pData->mapAddr, dataLen)==-1) {
263 }
Frank Tang69c72a62019-04-03 21:41:21 -0700264 pData->pHeader=nullptr;
jshin@chromium.org6f31ac32014-03-26 22:15:14 +0000265 pData->map=0;
Frank Tang69c72a62019-04-03 21:41:21 -0700266 pData->mapAddr=nullptr;
jshin@chromium.org6f31ac32014-03-26 22:15:14 +0000267 }
268 }
269
270
271
272#elif MAP_IMPLEMENTATION==MAP_STDIO
273 /* copy of the filestrm.c/T_FileStream_size() implementation */
274 static int32_t
275 umap_fsize(FILE *f) {
276 int32_t savedPos = ftell(f);
277 int32_t size = 0;
278
279 /*Changes by Bertrand A. D. doesn't affect the current position
280 goes to the end of the file before ftell*/
281 fseek(f, 0, SEEK_END);
282 size = (int32_t)ftell(f);
283 fseek(f, savedPos, SEEK_SET);
284 return size;
285 }
286
287 U_CFUNC UBool
Jungshik Shin42d50272018-10-24 01:22:09 -0700288 uprv_mapFile(UDataMemory *pData, const char *path, UErrorCode *status) {
jshin@chromium.org6f31ac32014-03-26 22:15:14 +0000289 FILE *file;
290 int32_t fileLength;
291 void *p;
292
Jungshik Shin42d50272018-10-24 01:22:09 -0700293 if (U_FAILURE(*status)) {
Frank Tang1f164ee2022-11-08 12:31:27 -0800294 return false;
Jungshik Shin42d50272018-10-24 01:22:09 -0700295 }
296
jshin@chromium.org6f31ac32014-03-26 22:15:14 +0000297 UDataMemory_init(pData); /* Clear the output struct. */
298 /* open the input file */
299 file=fopen(path, "rb");
Frank Tang69c72a62019-04-03 21:41:21 -0700300 if(file==nullptr) {
Frank Tang1f164ee2022-11-08 12:31:27 -0800301 return false;
jshin@chromium.org6f31ac32014-03-26 22:15:14 +0000302 }
303
304 /* get the file length */
305 fileLength=umap_fsize(file);
306 if(ferror(file) || fileLength<=20) {
307 fclose(file);
Frank Tang1f164ee2022-11-08 12:31:27 -0800308 return false;
jshin@chromium.org6f31ac32014-03-26 22:15:14 +0000309 }
310
311 /* allocate the memory to hold the file data */
312 p=uprv_malloc(fileLength);
Frank Tang69c72a62019-04-03 21:41:21 -0700313 if(p==nullptr) {
jshin@chromium.org6f31ac32014-03-26 22:15:14 +0000314 fclose(file);
Jungshik Shin42d50272018-10-24 01:22:09 -0700315 *status = U_MEMORY_ALLOCATION_ERROR;
Frank Tang1f164ee2022-11-08 12:31:27 -0800316 return false;
jshin@chromium.org6f31ac32014-03-26 22:15:14 +0000317 }
318
319 /* read the file */
320 if(fileLength!=fread(p, 1, fileLength, file)) {
321 uprv_free(p);
322 fclose(file);
Frank Tang1f164ee2022-11-08 12:31:27 -0800323 return false;
jshin@chromium.org6f31ac32014-03-26 22:15:14 +0000324 }
325
326 fclose(file);
327 pData->map=p;
328 pData->pHeader=(const DataHeader *)p;
329 pData->mapAddr=p;
Frank Tang1f164ee2022-11-08 12:31:27 -0800330 return true;
jshin@chromium.org6f31ac32014-03-26 22:15:14 +0000331 }
332
333 U_CFUNC void
334 uprv_unmapFile(UDataMemory *pData) {
Frank Tang69c72a62019-04-03 21:41:21 -0700335 if(pData!=nullptr && pData->map!=nullptr) {
jshin@chromium.org6f31ac32014-03-26 22:15:14 +0000336 uprv_free(pData->map);
Frank Tang69c72a62019-04-03 21:41:21 -0700337 pData->map = nullptr;
338 pData->mapAddr = nullptr;
339 pData->pHeader = nullptr;
jshin@chromium.org6f31ac32014-03-26 22:15:14 +0000340 }
341 }
342
343
344#elif MAP_IMPLEMENTATION==MAP_390DLL
345 /* 390 specific Library Loading.
346 * This is the only platform left that dynamically loads an ICU Data Library.
347 * All other platforms use .data files when dynamic loading is required, but
348 * this turn out to be awkward to support in 390 batch mode.
349 *
350 * The idea here is to hide the fact that 390 is using dll loading from the
351 * rest of ICU, and make it look like there is file loading happening.
352 *
353 */
354
355 static char *strcpy_returnEnd(char *dest, const char *src)
356 {
357 while((*dest=*src)!=0) {
358 ++dest;
359 ++src;
360 }
361 return dest;
362 }
363
364 /*------------------------------------------------------------------------------
365 *
366 * computeDirPath given a user-supplied path of an item to be opened,
367 * compute and return
368 * - the full directory path to be used
369 * when opening the file.
370 * - Pointer to null at end of above returned path
371 *
372 * Parameters:
373 * path: input path. Buffer is not altered.
374 * pathBuffer: Output buffer. Any contents are overwritten.
375 *
376 * Returns:
377 * Pointer to null termination in returned pathBuffer.
378 *
379 * TODO: This works the way ICU historically has, but the
380 * whole data fallback search path is so complicated that
Jungshik Shin42d50272018-10-24 01:22:09 -0700381 * probably almost no one will ever really understand it,
jshin@chromium.org6f31ac32014-03-26 22:15:14 +0000382 * the potential for confusion is large. (It's not just
383 * this one function, but the whole scheme.)
384 *
385 *------------------------------------------------------------------------------*/
386 static char *uprv_computeDirPath(const char *path, char *pathBuffer)
387 {
388 char *finalSlash; /* Ptr to last dir separator in input path, or null if none. */
389 int32_t pathLen; /* Length of the returned directory path */
390
391 finalSlash = 0;
392 if (path != 0) {
393 finalSlash = uprv_strrchr(path, U_FILE_SEP_CHAR);
394 }
395
396 *pathBuffer = 0;
397 if (finalSlash == 0) {
398 /* No user-supplied path.
399 * Copy the ICU_DATA path to the path buffer and return that*/
400 const char *icuDataDir;
401 icuDataDir=u_getDataDirectory();
Frank Tang69c72a62019-04-03 21:41:21 -0700402 if(icuDataDir!=nullptr && *icuDataDir!=0) {
jshin@chromium.org6f31ac32014-03-26 22:15:14 +0000403 return strcpy_returnEnd(pathBuffer, icuDataDir);
404 } else {
405 /* there is no icuDataDir either. Just return the empty pathBuffer. */
406 return pathBuffer;
407 }
408 }
409
410 /* User supplied path did contain a directory portion.
411 * Copy it to the output path buffer */
412 pathLen = (int32_t)(finalSlash - path + 1);
413 uprv_memcpy(pathBuffer, path, pathLen);
414 *(pathBuffer+pathLen) = 0;
415 return pathBuffer+pathLen;
416 }
417
418
419# define DATA_TYPE "dat"
420
Jungshik Shin42d50272018-10-24 01:22:09 -0700421 U_CFUNC UBool uprv_mapFile(UDataMemory *pData, const char *path, UErrorCode *status) {
jshin@chromium.org6f31ac32014-03-26 22:15:14 +0000422 const char *inBasename;
423 char *basename;
424 char pathBuffer[1024];
425 const DataHeader *pHeader;
426 dllhandle *handle;
427 void *val=0;
428
Jungshik Shin42d50272018-10-24 01:22:09 -0700429 if (U_FAILURE(*status)) {
Frank Tang1f164ee2022-11-08 12:31:27 -0800430 return false;
Jungshik Shin42d50272018-10-24 01:22:09 -0700431 }
432
jshin@chromium.org6f31ac32014-03-26 22:15:14 +0000433 inBasename=uprv_strrchr(path, U_FILE_SEP_CHAR);
Frank Tang69c72a62019-04-03 21:41:21 -0700434 if(inBasename==nullptr) {
jshin@chromium.org6f31ac32014-03-26 22:15:14 +0000435 inBasename = path;
436 } else {
437 inBasename++;
438 }
439 basename=uprv_computeDirPath(path, pathBuffer);
440 if(uprv_strcmp(inBasename, U_ICUDATA_NAME".dat") != 0) {
441 /* must mmap file... for build */
442 int fd;
443 int length;
444 struct stat mystat;
445 void *data;
446 UDataMemory_init(pData); /* Clear the output struct. */
447
448 /* determine the length of the file */
449 if(stat(path, &mystat)!=0 || mystat.st_size<=0) {
Frank Tang1f164ee2022-11-08 12:31:27 -0800450 return false;
jshin@chromium.org6f31ac32014-03-26 22:15:14 +0000451 }
452 length=mystat.st_size;
453
454 /* open the file */
455 fd=open(path, O_RDONLY);
456 if(fd==-1) {
Frank Tang1f164ee2022-11-08 12:31:27 -0800457 return false;
jshin@chromium.org6f31ac32014-03-26 22:15:14 +0000458 }
459
460 /* get a view of the mapping */
461 data=mmap(0, length, PROT_READ, MAP_PRIVATE, fd, 0);
462 close(fd); /* no longer needed */
463 if(data==MAP_FAILED) {
Jungshik Shin42d50272018-10-24 01:22:09 -0700464 // Possibly check the errorno value for ENOMEM, and report U_MEMORY_ALLOCATION_ERROR?
Frank Tang1f164ee2022-11-08 12:31:27 -0800465 return false;
jshin@chromium.org6f31ac32014-03-26 22:15:14 +0000466 }
467 pData->map = (char *)data + length;
468 pData->pHeader=(const DataHeader *)data;
469 pData->mapAddr = data;
Frank Tang1f164ee2022-11-08 12:31:27 -0800470 return true;
jshin@chromium.org6f31ac32014-03-26 22:15:14 +0000471 }
472
473# ifdef OS390BATCH
474 /* ### hack: we still need to get u_getDataDirectory() fixed
475 for OS/390 (batch mode - always return "//"? )
476 and this here straightened out with LIB_PREFIX and LIB_SUFFIX (both empty?!)
477 This is probably due to the strange file system on OS/390. It's more like
478 a database with short entry names than a typical file system. */
479 /* U_ICUDATA_NAME should always have the correct name */
480 /* BUT FOR BATCH MODE IT IS AN EXCEPTION BECAUSE */
481 /* THE FIRST THREE LETTERS ARE PREASSIGNED TO THE */
482 /* PROJECT!!!!! */
483 uprv_strcpy(pathBuffer, "IXMI" U_ICU_VERSION_SHORT "DA");
484# else
485 /* set up the library name */
486 uprv_strcpy(basename, LIB_PREFIX U_LIBICUDATA_NAME U_ICU_VERSION_SHORT LIB_SUFFIX);
487# endif
488
489# ifdef UDATA_DEBUG
490 fprintf(stderr, "dllload: %s ", pathBuffer);
491# endif
492
493 handle=dllload(pathBuffer);
494
495# ifdef UDATA_DEBUG
496 fprintf(stderr, " -> %08X\n", handle );
497# endif
498
Frank Tang69c72a62019-04-03 21:41:21 -0700499 if(handle != nullptr) {
jshin@chromium.org6f31ac32014-03-26 22:15:14 +0000500 /* we have a data DLL - what kind of lookup do we need here? */
501 /* try to find the Table of Contents */
502 UDataMemory_init(pData); /* Clear the output struct. */
503 val=dllqueryvar((dllhandle*)handle, U_ICUDATA_ENTRY_NAME);
504 if(val == 0) {
505 /* failed... so keep looking */
Frank Tang1f164ee2022-11-08 12:31:27 -0800506 return false;
jshin@chromium.org6f31ac32014-03-26 22:15:14 +0000507 }
508# ifdef UDATA_DEBUG
509 fprintf(stderr, "dllqueryvar(%08X, %s) -> %08X\n", handle, U_ICUDATA_ENTRY_NAME, val);
510# endif
511
512 pData->pHeader=(const DataHeader *)val;
Frank Tang1f164ee2022-11-08 12:31:27 -0800513 return true;
jshin@chromium.org6f31ac32014-03-26 22:15:14 +0000514 } else {
Frank Tang1f164ee2022-11-08 12:31:27 -0800515 return false; /* no handle */
jshin@chromium.org6f31ac32014-03-26 22:15:14 +0000516 }
517 }
518
519 U_CFUNC void uprv_unmapFile(UDataMemory *pData) {
Frank Tang69c72a62019-04-03 21:41:21 -0700520 if(pData!=nullptr && pData->map!=nullptr) {
jshin@chromium.org6f31ac32014-03-26 22:15:14 +0000521 uprv_free(pData->map);
Frank Tang69c72a62019-04-03 21:41:21 -0700522 pData->map = nullptr;
523 pData->mapAddr = nullptr;
524 pData->pHeader = nullptr;
jshin@chromium.org6f31ac32014-03-26 22:15:14 +0000525 }
526 }
527
528#else
529# error MAP_IMPLEMENTATION is set incorrectly
530#endif