1 /*
2 * IP2Location C library is distributed under MIT license
3 * Copyright (c) 2013 IP2Location.com. support at ip2location dot com
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the MIT license
7 * License as published by the Free Software Foundation; either
8 */
9
10 #ifdef WIN32
11 #include <winsock2.h>
12 #else
13 #include <stdint.h>
14 #include <strings.h>
15 #include <unistd.h>
16 #include <sys/mman.h>
17 #endif
18
19
20 #include <stdio.h>
21 #include <sys/types.h>
22 #include <sys/stat.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <fcntl.h>
26 #include <errno.h>
27
28
29 #include "IP2Location.h"
30 #include "IP2Loc_DBInterface.h"
31
32 #define IP2LOCATION_SHM "/IP2location_Shm"
33 #define MAP_ADDR 4194500608
34
35 //Static variables
36 static enum IP2Location_mem_type DB_access_type = IP2LOCATION_FILE_IO;
37 static void *cache_shm_ptr;
38 #ifndef WIN32
39 static int32_t shm_fd;
40 #else
41 #ifdef WIN32
42 HANDLE shm_fd;
43 #endif
44 #endif
45
46 //Static functions
47 static int32_t IP2Location_DB_Load_to_mem(FILE *filehandle, void *cache_shm_ptr, int64_t size);
48
49 //Description: set the DB access method as memory cache and read the file into cache
IP2Location_DB_set_memory_cache(FILE * filehandle)50 int32_t IP2Location_DB_set_memory_cache(FILE *filehandle)
51 {
52 struct stat statbuf;
53 DB_access_type = IP2LOCATION_CACHE_MEMORY;
54 if(fstat(fileno(filehandle), &statbuf) == -1)
55 {
56 DB_access_type = IP2LOCATION_FILE_IO;
57 return -1;
58 }
59
60 if ( (cache_shm_ptr = malloc(statbuf.st_size + 1)) == NULL )
61 {
62 DB_access_type = IP2LOCATION_FILE_IO;
63 return -1;
64 }
65 if( IP2Location_DB_Load_to_mem(filehandle, cache_shm_ptr, statbuf.st_size) == -1 )
66 {
67 DB_access_type = IP2LOCATION_FILE_IO;
68 free(cache_shm_ptr);
69 return -1;
70 }
71 return 0;
72 }
73
74 //Description: set the DB access method as shared memory
75 #ifndef WIN32
IP2Location_DB_set_shared_memory(FILE * filehandle)76 int32_t IP2Location_DB_set_shared_memory(FILE *filehandle)
77 {
78 struct stat statbuf;
79 int32_t DB_loaded = 1;
80 void *addr = (void*)MAP_ADDR;
81
82 DB_access_type = IP2LOCATION_SHARED_MEMORY;
83
84 if ( ( shm_fd = shm_open(IP2LOCATION_SHM, O_RDWR | O_CREAT | O_EXCL, 0777)) != -1 )
85 {
86 DB_loaded = 0;
87 }
88 else if ((shm_fd = shm_open(IP2LOCATION_SHM, O_RDWR , 0777)) == -1 )
89 {
90 DB_access_type = IP2LOCATION_FILE_IO;
91 return -1;
92 }
93 if(fstat(fileno(filehandle), &statbuf) == -1)
94 {
95 close(shm_fd);
96 if( DB_loaded == 0 )
97 shm_unlink(IP2LOCATION_SHM);
98 DB_access_type = IP2LOCATION_FILE_IO;
99 return -1;
100 }
101
102 if( DB_loaded == 0 && ftruncate(shm_fd, statbuf.st_size + 1) == -1)
103 {
104 close(shm_fd);
105 shm_unlink(IP2LOCATION_SHM);
106 DB_access_type = IP2LOCATION_FILE_IO;
107 return -1;
108 }
109
110 cache_shm_ptr = mmap(addr, statbuf.st_size + 1, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);
111 if (cache_shm_ptr == (void *) -1)
112 {
113 close(shm_fd);
114 if( DB_loaded == 0 )
115 shm_unlink(IP2LOCATION_SHM);
116 DB_access_type = IP2LOCATION_FILE_IO;
117 return -1;
118 }
119 if( DB_loaded == 0 )
120 {
121 if ( IP2Location_DB_Load_to_mem(filehandle, cache_shm_ptr, statbuf.st_size) == -1 )
122 {
123 munmap(cache_shm_ptr, statbuf.st_size);
124 close(shm_fd);
125 shm_unlink(IP2LOCATION_SHM);
126 DB_access_type = IP2LOCATION_FILE_IO;
127 return -1;
128 }
129 }
130 return 0;
131 }
132 #else
133 #ifdef WIN32
IP2Location_DB_set_shared_memory(FILE * filehandle)134 int32_t IP2Location_DB_set_shared_memory(FILE *filehandle)
135 {
136 struct stat statbuf;
137 int32_t DB_loaded = 1;
138
139 DB_access_type = IP2LOCATION_SHARED_MEMORY;
140
141 if(fstat(fileno(filehandle), &statbuf) == -1)
142 {
143 DB_access_type = IP2LOCATION_FILE_IO;
144 return -1;
145 }
146
147 shm_fd = CreateFileMapping(
148 INVALID_HANDLE_VALUE,
149 NULL,
150 PAGE_READWRITE,
151 0,
152 statbuf.st_size + 1,
153 TEXT(IP2LOCATION_SHM));
154 if(shm_fd == NULL)
155 {
156 DB_access_type = IP2LOCATION_FILE_IO;
157 return -1;
158 }
159
160 DB_loaded = (GetLastError() == ERROR_ALREADY_EXISTS);
161
162 cache_shm_ptr = MapViewOfFile(
163 shm_fd,
164 FILE_MAP_WRITE,
165 0,
166 0,
167 0);
168
169 if(cache_shm_ptr == NULL)
170 {
171 UnmapViewOfFile(cache_shm_ptr);
172 DB_access_type = IP2LOCATION_FILE_IO;
173 return -1;
174 }
175
176 if( DB_loaded == 0 )
177 {
178 if ( IP2Location_DB_Load_to_mem(filehandle, cache_shm_ptr, statbuf.st_size) == -1 )
179 {
180 UnmapViewOfFile(cache_shm_ptr);
181 CloseHandle(shm_fd);
182 DB_access_type = IP2LOCATION_FILE_IO;
183 return -1;
184 }
185 }
186 return 0;
187 }
188 #endif
189 #endif
190
191 //Load the DB file into shared/cache memory
IP2Location_DB_Load_to_mem(FILE * filehandle,void * memory,int64_t size)192 int32_t IP2Location_DB_Load_to_mem(FILE *filehandle, void *memory, int64_t size)
193 {
194 fseek(filehandle, SEEK_SET, 0);
195 if ( fread(memory, size, 1, filehandle) != 1 )
196 return -1;
197 return 0;
198 }
199
200 //Close the corresponding memory, based on the opened option.
IP2Location_DB_close(FILE * filehandle)201 int32_t IP2Location_DB_close(FILE *filehandle)
202 {
203 struct stat statbuf;
204
205 if ( DB_access_type == IP2LOCATION_CACHE_MEMORY )
206 {
207 if( cache_shm_ptr != NULL )
208 free(cache_shm_ptr);
209 }
210 else if ( DB_access_type == IP2LOCATION_SHARED_MEMORY )
211 {
212 if( cache_shm_ptr != NULL )
213 {
214 #ifndef WIN32
215 if(fstat(fileno(filehandle), &statbuf) == 0)
216 {
217 munmap(cache_shm_ptr, statbuf.st_size);
218 }
219 close(shm_fd);
220 #else
221 #ifdef WIN32
222 UnmapViewOfFile(cache_shm_ptr);
223 CloseHandle(shm_fd);
224 #endif
225 #endif
226 }
227 }
228
229 if ( filehandle != NULL )
230 fclose(filehandle);
231
232 DB_access_type = IP2LOCATION_FILE_IO;
233 return 0;
234 }
235
236 #ifndef WIN32
IP2Location_DB_del_shm()237 void IP2Location_DB_del_shm()
238 {
239 shm_unlink(IP2LOCATION_SHM);
240 }
241 #else
242 #ifdef WIN32
IP2Location_DB_del_shm()243 void IP2Location_DB_del_shm()
244 {
245 }
246 #endif
247 #endif
248
IP2Location_readIPv6Address(FILE * handle,uint32_t position)249 struct in6_addr_local IP2Location_readIPv6Address(FILE *handle, uint32_t position)
250 {
251 int i,j;
252 struct in6_addr_local addr6;
253 for( i = 0, j = 15; i < 16; i++, j-- )
254 {
255 addr6.u.addr8[i] = IP2Location_read8(handle, position + j);
256 }
257 return addr6;
258 }
259
IP2Location_read32(FILE * handle,uint32_t position)260 uint32_t IP2Location_read32(FILE *handle, uint32_t position)
261 {
262 uint8_t byte1 = 0;
263 uint8_t byte2 = 0;
264 uint8_t byte3 = 0;
265 uint8_t byte4 = 0;
266 uint8_t *cache_shm = cache_shm_ptr;
267 size_t temp;
268
269 //Read from file
270 if (DB_access_type == IP2LOCATION_FILE_IO && handle != NULL)
271 {
272 fseek(handle, position-1, 0);
273 temp = fread(&byte1, 1, 1, handle);
274 temp = fread(&byte2, 1, 1, handle);
275 temp = fread(&byte3, 1, 1, handle);
276 temp = fread(&byte4, 1, 1, handle);
277 }
278 else
279 {
280 byte1 = cache_shm[ position - 1 ];
281 byte2 = cache_shm[ position ];
282 byte3 = cache_shm[ position + 1 ];
283 byte4 = cache_shm[ position + 2 ];
284 }
285 return ((byte4 << 24) | (byte3 << 16) | (byte2 << 8) | (byte1));
286 }
287
IP2Location_read8(FILE * handle,uint32_t position)288 uint8_t IP2Location_read8(FILE *handle, uint32_t position)
289 {
290 uint8_t ret = 0;
291 uint8_t *cache_shm = cache_shm_ptr;
292 size_t temp;
293
294 if (DB_access_type == IP2LOCATION_FILE_IO && handle != NULL)
295 {
296 fseek(handle, position-1, 0);
297 temp = fread(&ret, 1, 1, handle);
298 }
299 else
300 {
301 ret = cache_shm[ position - 1 ];
302 }
303 return ret;
304 }
305
IP2Location_readStr(FILE * handle,uint32_t position)306 char *IP2Location_readStr(FILE *handle, uint32_t position)
307 {
308 uint8_t size = 0;
309 char *str = 0;
310 uint8_t *cache_shm = cache_shm_ptr;
311 size_t temp;
312 if (DB_access_type == IP2LOCATION_FILE_IO && handle != NULL)
313 {
314 fseek(handle, position, 0);
315 temp = fread(&size, 1, 1, handle);
316 str = (char *)malloc(size+1);
317 memset(str, 0, size+1);
318 temp = fread(str, size, 1, handle);
319 }
320 else
321 {
322 size = cache_shm[ position ];
323 str = (char *)malloc(size+1);
324 memset(str, 0, size+1);
325 memcpy((void*) str, (void*)&cache_shm[ position + 1 ], size);
326 }
327 return str;
328 }
329
IP2Location_readFloat(FILE * handle,uint32_t position)330 float IP2Location_readFloat(FILE *handle, uint32_t position)
331 {
332 float ret = 0.0;
333 uint8_t *cache_shm = cache_shm_ptr;
334 size_t temp;
335
336 #if defined(_SUN_) || defined(__powerpc__) || defined(__ppc__) || defined(__ppc64__) || defined(__powerpc64__)
337 char * p = (char *) &ret;
338
339 // for SUN SPARC, have to reverse the byte order
340 if (DB_access_type == IP2LOCATION_FILE_IO && handle != NULL)
341 {
342 fseek(handle, position-1, 0);
343 temp = fread(p+3, 1, 1, handle);
344 temp = fread(p+2, 1, 1, handle);
345 temp = fread(p+1, 1, 1, handle);
346 temp = fread(p, 1, 1, handle);
347 }
348 else
349 {
350 *(p+3) = cache_shm[ position - 1 ];
351 *(p+2) = cache_shm[ position ];
352 *(p+1) = cache_shm[ position + 1 ];
353 *(p) = cache_shm[ position + 2 ];
354 }
355 #else
356 if (DB_access_type == IP2LOCATION_FILE_IO && handle != NULL)
357 {
358 fseek(handle, position-1, 0);
359 temp = fread(&ret, 4, 1, handle);
360 }
361 else
362 {
363 memcpy((void*) &ret, (void*)&cache_shm[ position - 1 ], 4);
364 }
365 #endif
366 return ret;
367 }
368
369
370