1 /*************************************************************************************************
2 * Emulation of system calls
3 * Copyright (C) 2000-2007 Mikio Hirabayashi
4 * This file is part of QDBM, Quick Database Manager.
5 * QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU
6 * Lesser General Public License as published by the Free Software Foundation; either version
7 * 2.1 of the License or any later version. QDBM is distributed in the hope that it will be
8 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
9 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
10 * details.
11 * You should have received a copy of the GNU Lesser General Public License along with QDBM; if
12 * not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
13 * 02111-1307 USA.
14 *************************************************************************************************/
15
16
17 #include "myconf.h"
18
19
20
21 /*************************************************************************************************
22 * for dosish filesystems
23 *************************************************************************************************/
24
25
26 #if defined(_SYS_MSVC_) || defined(_SYS_MINGW_) || defined(_SYS_CYGWIN_)
27
28
29 #define DOSPATHBUFSIZ 8192
30
31
_qdbm_win32_lstat(const char * pathname,struct stat * buf)32 int _qdbm_win32_lstat(const char *pathname, struct stat *buf){
33 char pbuf[DOSPATHBUFSIZ], *p;
34 int inode;
35 if(stat(pathname, buf) == -1) return -1;
36 if(GetFullPathName(pathname, DOSPATHBUFSIZ, pbuf, &p) != 0){
37 inode = 11003;
38 for(p = pbuf; *p != '\0'; p++){
39 inode = inode * 31 + *(unsigned char *)p;
40 }
41 buf->st_ino = (inode * 911) & 0x7FFF;
42 }
43 return 0;
44 }
45
46
47 #endif
48
49
50
51 /*************************************************************************************************
52 * for POSIX thread
53 *************************************************************************************************/
54
55
56 #if defined(MYPTHREAD)
57
58
59 #include <pthread.h>
60
61
62 #define PTKEYMAX 8
63
64
65 struct { void *ptr; pthread_key_t key; } _qdbm_ptkeys[PTKEYMAX];
66 int _qdbm_ptknum = 0;
67
68
69 static void *_qdbm_gettsd(void *ptr, int size, const void *initval);
70
71
_qdbm_settsd(void * ptr,int size,const void * initval)72 void *_qdbm_settsd(void *ptr, int size, const void *initval){
73 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
74 char *val;
75 if((val = _qdbm_gettsd(ptr, size, initval)) != NULL) return val;
76 if(pthread_mutex_lock(&mutex) != 0) return NULL;
77 if((val = _qdbm_gettsd(ptr, size, initval)) != NULL){
78 pthread_mutex_unlock(&mutex);
79 return val;
80 }
81 if(_qdbm_ptknum >= PTKEYMAX){
82 pthread_mutex_unlock(&mutex);
83 return NULL;
84 }
85 _qdbm_ptkeys[_qdbm_ptknum].ptr = ptr;
86 if(pthread_key_create(&(_qdbm_ptkeys[_qdbm_ptknum].key), free) != 0){
87 pthread_mutex_unlock(&mutex);
88 return NULL;
89 }
90 if(!(val = malloc(size))){
91 pthread_key_delete(_qdbm_ptkeys[_qdbm_ptknum].key);
92 pthread_mutex_unlock(&mutex);
93 return NULL;
94 }
95 memcpy(val, initval, size);
96 if(pthread_setspecific(_qdbm_ptkeys[_qdbm_ptknum].key, val) != 0){
97 free(val);
98 pthread_key_delete(_qdbm_ptkeys[_qdbm_ptknum].key);
99 pthread_mutex_unlock(&mutex);
100 return NULL;
101 }
102 _qdbm_ptknum++;
103 pthread_mutex_unlock(&mutex);
104 return val;
105 }
106
107
_qdbm_gettsd(void * ptr,int size,const void * initval)108 static void *_qdbm_gettsd(void *ptr, int size, const void *initval){
109 char *val;
110 int i;
111 for(i = 0; i < _qdbm_ptknum; i++){
112 if(_qdbm_ptkeys[i].ptr == ptr){
113 if(!(val = pthread_getspecific(_qdbm_ptkeys[i].key))){
114 if(!(val = malloc(size))) return NULL;
115 memcpy(val, initval, size);
116 if(pthread_setspecific(_qdbm_ptkeys[i].key, val) != 0){
117 free(val);
118 return NULL;
119 }
120 }
121 return val;
122 }
123 }
124 return NULL;
125 }
126
127
128 #endif
129
130
131
132 /*************************************************************************************************
133 * for systems without mmap
134 *************************************************************************************************/
135
136
137 #if defined(_SYS_MSVC_) || defined(_SYS_MINGW_)
138
139
140 #define MMFDESCMAX 2048
141
142
143 struct { void *start; HANDLE handle; } mmhandles[MMFDESCMAX];
144 int mmhnum = 0;
145 CRITICAL_SECTION mmcsec;
146
147
148 static void _qdbm_delete_mmap_env(void);
149
150
_qdbm_mmap(void * start,size_t length,int prot,int flags,int fd,off_t offset)151 void *_qdbm_mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset){
152 static volatile long first = TRUE;
153 static volatile long ready = FALSE;
154 HANDLE handle;
155 int i;
156 if(InterlockedExchange((void *)&first, FALSE)){
157 InitializeCriticalSection(&mmcsec);
158 atexit(_qdbm_delete_mmap_env);
159 InterlockedExchange((void *)&ready, TRUE);
160 }
161 while(!InterlockedCompareExchange((void *)&ready, TRUE, TRUE)){
162 Sleep(1);
163 }
164 if(fd < 0 || flags & MAP_FIXED) return MAP_FAILED;
165 if(!(handle = CreateFileMapping((HANDLE)_get_osfhandle(fd), NULL,
166 (prot & PROT_WRITE) ? PAGE_READWRITE : PAGE_READONLY,
167 0, length, NULL))) return MAP_FAILED;
168 if(!(start = MapViewOfFile(handle, (prot & PROT_WRITE) ? FILE_MAP_WRITE : FILE_MAP_READ,
169 0, 0, length))){
170 CloseHandle(handle);
171 return MAP_FAILED;
172 }
173 EnterCriticalSection(&mmcsec);
174 if(mmhnum >= MMFDESCMAX - 1){
175 UnmapViewOfFile(start);
176 CloseHandle(handle);
177 LeaveCriticalSection(&mmcsec);
178 return MAP_FAILED;
179 }
180 for(i = 0; i < MMFDESCMAX; i++){
181 if(!mmhandles[i].start){
182 mmhandles[i].start = start;
183 mmhandles[i].handle = handle;
184 break;
185 }
186 }
187 mmhnum++;
188 LeaveCriticalSection(&mmcsec);
189 return start;
190 }
191
192
_qdbm_munmap(void * start,size_t length)193 int _qdbm_munmap(void *start, size_t length){
194 HANDLE handle;
195 int i;
196 EnterCriticalSection(&mmcsec);
197 handle = NULL;
198 for(i = 0; i < MMFDESCMAX; i++){
199 if(mmhandles[i].start == start){
200 handle = mmhandles[i].handle;
201 mmhandles[i].start = NULL;
202 mmhandles[i].handle = NULL;
203 break;
204 }
205 }
206 if(!handle){
207 LeaveCriticalSection(&mmcsec);
208 return -1;
209 }
210 mmhnum--;
211 LeaveCriticalSection(&mmcsec);
212 if(!UnmapViewOfFile(start)){
213 CloseHandle(handle);
214 return -1;
215 }
216 if(!CloseHandle(handle)) return -1;
217 return 0;
218 }
219
220
_qdbm_msync(const void * start,size_t length,int flags)221 int _qdbm_msync(const void *start, size_t length, int flags){
222 if(!FlushViewOfFile(start, length)) return -1;
223 return 0;
224 }
225
226
_qdbm_delete_mmap_env(void)227 static void _qdbm_delete_mmap_env(void){
228 DeleteCriticalSection(&mmcsec);
229 }
230
231
232 #elif defined(_SYS_FREEBSD_) || defined(_SYS_NETBSD_) || defined(_SYS_OPENBSD_) || \
233 defined(_SYS_AIX_) || defined(_SYS_RISCOS_) || defined(MYNOMMAP)
234
235
_qdbm_mmap(void * start,size_t length,int prot,int flags,int fd,off_t offset)236 void *_qdbm_mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset){
237 char *buf, *wp;
238 int rv, rlen;
239 if(flags & MAP_FIXED) return MAP_FAILED;
240 if(lseek(fd, SEEK_SET, offset) == -1) return MAP_FAILED;
241 if(!(buf = malloc(sizeof(int) * 3 + length))) return MAP_FAILED;
242 wp = buf;
243 *(int *)wp = fd;
244 wp += sizeof(int);
245 *(int *)wp = offset;
246 wp += sizeof(int);
247 *(int *)wp = prot;
248 wp += sizeof(int);
249 rlen = 0;
250 while((rv = read(fd, wp + rlen, length - rlen)) > 0){
251 rlen += rv;
252 }
253 if(rv == -1 || rlen != length){
254 free(buf);
255 return MAP_FAILED;
256 }
257 return wp;
258 }
259
260
_qdbm_munmap(void * start,size_t length)261 int _qdbm_munmap(void *start, size_t length){
262 char *buf, *rp;
263 int fd, offset, prot, rv, wlen;
264 buf = (char *)start - sizeof(int) * 3;
265 rp = buf;
266 fd = *(int *)rp;
267 rp += sizeof(int);
268 offset = *(int *)rp;
269 rp += sizeof(int);
270 prot = *(int *)rp;
271 rp += sizeof(int);
272 if(prot & PROT_WRITE){
273 if(lseek(fd, offset, SEEK_SET) == -1){
274 free(buf);
275 return -1;
276 }
277 wlen = 0;
278 while(wlen < (int)length){
279 rv = write(fd, rp + wlen, length - wlen);
280 if(rv == -1){
281 if(errno == EINTR) continue;
282 free(buf);
283 return -1;
284 }
285 wlen += rv;
286 }
287 }
288 free(buf);
289 return 0;
290 }
291
292
_qdbm_msync(const void * start,size_t length,int flags)293 int _qdbm_msync(const void *start, size_t length, int flags){
294 char *buf, *rp;
295 int fd, offset, prot, rv, wlen;
296 buf = (char *)start - sizeof(int) * 3;
297 rp = buf;
298 fd = *(int *)rp;
299 rp += sizeof(int);
300 offset = *(int *)rp;
301 rp += sizeof(int);
302 prot = *(int *)rp;
303 rp += sizeof(int);
304 if(prot & PROT_WRITE){
305 if(lseek(fd, offset, SEEK_SET) == -1) return -1;
306 wlen = 0;
307 while(wlen < (int)length){
308 rv = write(fd, rp + wlen, length - wlen);
309 if(rv == -1){
310 if(errno == EINTR) continue;
311 return -1;
312 }
313 wlen += rv;
314 }
315 }
316 return 0;
317 }
318
319
320 #endif
321
322
323
324 /*************************************************************************************************
325 * for reentrant time routines
326 *************************************************************************************************/
327
328
329 #if defined(_SYS_LINUX_) || defined(_SYS_FREEBSD_) || defined(_SYS_OPENBSD_) || \
330 defined(_SYS_NETBSD_) || defined(_SYS_SUNOS_) || defined(_SYS_HPUX_) || \
331 defined(_SYS_MACOSX_) || defined(_SYS_CYGWIN_)
332
333
_qdbm_gmtime(const time_t * timep,struct tm * result)334 struct tm *_qdbm_gmtime(const time_t *timep, struct tm *result){
335 return gmtime_r(timep, result);
336 }
337
338
_qdbm_localtime(const time_t * timep,struct tm * result)339 struct tm *_qdbm_localtime(const time_t *timep, struct tm *result){
340 return localtime_r(timep, result);
341 }
342
343
344 # else
345
346
_qdbm_gmtime(const time_t * timep,struct tm * result)347 struct tm *_qdbm_gmtime(const time_t *timep, struct tm *result){
348 return gmtime(timep);
349 }
350
351
_qdbm_localtime(const time_t * timep,struct tm * result)352 struct tm *_qdbm_localtime(const time_t *timep, struct tm *result){
353 return localtime(timep);
354 }
355
356
357 # endif
358
359
360
361 /*************************************************************************************************
362 * for systems without times
363 *************************************************************************************************/
364
365
366 #if defined(_SYS_MSVC_) || defined(_SYS_MINGW_)
367
368
_qdbm_times(struct tms * buf)369 clock_t _qdbm_times(struct tms *buf){
370 buf->tms_utime = clock();
371 buf->tms_stime = 0;
372 buf->tms_cutime = 0;
373 buf->tms_cstime = 0;
374 return 0;
375 }
376
377
378 #endif
379
380
381
382 /*************************************************************************************************
383 * for Win32
384 *************************************************************************************************/
385
386
387 #if defined(_SYS_MSVC_) || defined(_SYS_MINGW_)
388
389
390 #define WINLOCKWAIT 100
391
392
_qdbm_win32_fcntl(int fd,int cmd,struct flock * lock)393 int _qdbm_win32_fcntl(int fd, int cmd, struct flock *lock){
394 HANDLE fh;
395 DWORD opt;
396 OVERLAPPED ol;
397 fh = (HANDLE)_get_osfhandle(fd);
398 opt = (cmd == F_SETLK) ? LOCKFILE_FAIL_IMMEDIATELY : 0;
399 if(lock->l_type == F_WRLCK) opt |= LOCKFILE_EXCLUSIVE_LOCK;
400 memset(&ol, 0, sizeof(OVERLAPPED));
401 ol.Offset = INT_MAX;
402 ol.OffsetHigh = 0;
403 ol.hEvent = 0;
404 if(!LockFileEx(fh, opt, 0, 1, 0, &ol)){
405 if(GetLastError() == ERROR_CALL_NOT_IMPLEMENTED){
406 while(TRUE){
407 if(LockFile(fh, 0, 0, 1, 0)) return 0;
408 Sleep(WINLOCKWAIT);
409 }
410 }
411 return -1;
412 }
413 return 0;
414 }
415
416
417 #endif
418
419
420 #if defined(_SYS_MSVC_)
421
422
_qdbm_win32_opendir(const char * name)423 DIR *_qdbm_win32_opendir(const char *name){
424 char expr[8192];
425 int len;
426 DIR *dir;
427 HANDLE fh;
428 WIN32_FIND_DATA data;
429 len = strlen(name);
430 if(len > 0 && name[len-1] == MYPATHCHR){
431 sprintf(expr, "%s*", name);
432 } else {
433 sprintf(expr, "%s%c*", name, MYPATHCHR);
434 }
435 if((fh = FindFirstFile(expr, &data)) == INVALID_HANDLE_VALUE) return NULL;
436 if(!(dir = malloc(sizeof(DIR)))){
437 FindClose(fh);
438 return NULL;
439 }
440 dir->fh = fh;
441 dir->data = data;
442 dir->first = TRUE;
443 return dir;
444 }
445
446
_qdbm_win32_closedir(DIR * dir)447 int _qdbm_win32_closedir(DIR *dir){
448 if(!FindClose(dir->fh)){
449 free(dir);
450 return -1;
451 }
452 free(dir);
453 return 0;
454 }
455
456
_qdbm_win32_readdir(DIR * dir)457 struct dirent *_qdbm_win32_readdir(DIR *dir){
458 if(dir->first){
459 sprintf(dir->de.d_name, "%s", dir->data.cFileName);
460 dir->first = FALSE;
461 return &(dir->de);
462 }
463 if(!FindNextFile(dir->fh, &(dir->data))) return NULL;
464 sprintf(dir->de.d_name, "%s", dir->data.cFileName);
465 return &(dir->de);
466 }
467
468
469 #endif
470
471
472
473 /*************************************************************************************************
474 * for checking information of the system
475 *************************************************************************************************/
476
477
478 #if defined(_SYS_LINUX_)
479
480
_qdbm_vmemavail(size_t size)481 int _qdbm_vmemavail(size_t size){
482 char buf[4096], *rp;
483 int fd, rv, bsiz;
484 double avail;
485 if((fd = open("/proc/meminfo", O_RDONLY, 00644)) == -1) return TRUE;
486 rv = TRUE;
487 if((bsiz = read(fd, buf, sizeof(buf) - 1)) > 0){
488 buf[bsiz] = '\0';
489 avail = -1;
490 if((rp = strstr(buf, "MemFree:")) != NULL){
491 rp = strchr(rp, ':') + 1;
492 avail = strtod(rp, NULL) * 1024.0;
493 if((rp = strstr(buf, "SwapFree:")) != NULL){
494 rp = strchr(rp, ':') + 1;
495 avail += strtod(rp, NULL) * 1024.0;
496 }
497 if(size >= avail) rv = FALSE;
498 }
499 }
500 close(fd);
501 return rv;
502 }
503
504
505 #elif defined(_SYS_MSVC_) || defined(_SYS_MINGW_) || defined(_SYS_CYGWIN_)
506
507
_qdbm_vmemavail(size_t size)508 int _qdbm_vmemavail(size_t size){
509 MEMORYSTATUS sbuf;
510 sbuf.dwLength = sizeof(MEMORYSTATUS);
511 GlobalMemoryStatus(&sbuf);
512 return size < sbuf.dwAvailVirtual;
513 }
514
515
516 #else
517
518
_qdbm_vmemavail(size_t size)519 int _qdbm_vmemavail(size_t size){
520 return TRUE;
521 }
522
523
524 #endif
525
526
527
528 /*************************************************************************************************
529 * for ZLIB
530 *************************************************************************************************/
531
532
533 #if defined(MYZLIB)
534
535
536 #include <zlib.h>
537
538 #define ZLIBBUFSIZ 8192
539
540
541 static char *_qdbm_deflate_impl(const char *ptr, int size, int *sp, int mode);
542 static char *_qdbm_inflate_impl(const char *ptr, int size, int *sp, int mode);
543 static unsigned int _qdbm_getcrc_impl(const char *ptr, int size);
544
545
546 char *(*_qdbm_deflate)(const char *, int, int *, int) = _qdbm_deflate_impl;
547 char *(*_qdbm_inflate)(const char *, int, int *, int) = _qdbm_inflate_impl;
548 unsigned int (*_qdbm_getcrc)(const char *, int) = _qdbm_getcrc_impl;
549
550
_qdbm_deflate_impl(const char * ptr,int size,int * sp,int mode)551 static char *_qdbm_deflate_impl(const char *ptr, int size, int *sp, int mode){
552 z_stream zs;
553 char *buf, *swap;
554 unsigned char obuf[ZLIBBUFSIZ];
555 int rv, asiz, bsiz, osiz;
556 if(size < 0) size = strlen(ptr);
557 zs.zalloc = Z_NULL;
558 zs.zfree = Z_NULL;
559 zs.opaque = Z_NULL;
560 switch(mode){
561 case _QDBM_ZMRAW:
562 if(deflateInit2(&zs, 5, Z_DEFLATED, -15, 7, Z_DEFAULT_STRATEGY) != Z_OK)
563 return NULL;
564 break;
565 case _QDBM_ZMGZIP:
566 if(deflateInit2(&zs, 6, Z_DEFLATED, 15 + 16, 9, Z_DEFAULT_STRATEGY) != Z_OK)
567 return NULL;
568 break;
569 default:
570 if(deflateInit2(&zs, 6, Z_DEFLATED, 15, 8, Z_DEFAULT_STRATEGY) != Z_OK)
571 return NULL;
572 break;
573 }
574 asiz = size + 16;
575 if(asiz < ZLIBBUFSIZ) asiz = ZLIBBUFSIZ;
576 if(!(buf = malloc(asiz))){
577 deflateEnd(&zs);
578 return NULL;
579 }
580 bsiz = 0;
581 zs.next_in = (unsigned char *)ptr;
582 zs.avail_in = size;
583 zs.next_out = obuf;
584 zs.avail_out = ZLIBBUFSIZ;
585 while((rv = deflate(&zs, Z_FINISH)) == Z_OK){
586 osiz = ZLIBBUFSIZ - zs.avail_out;
587 if(bsiz + osiz > asiz){
588 asiz = asiz * 2 + osiz;
589 if(!(swap = realloc(buf, asiz))){
590 free(buf);
591 deflateEnd(&zs);
592 return NULL;
593 }
594 buf = swap;
595 }
596 memcpy(buf + bsiz, obuf, osiz);
597 bsiz += osiz;
598 zs.next_out = obuf;
599 zs.avail_out = ZLIBBUFSIZ;
600 }
601 if(rv != Z_STREAM_END){
602 free(buf);
603 deflateEnd(&zs);
604 return NULL;
605 }
606 osiz = ZLIBBUFSIZ - zs.avail_out;
607 if(bsiz + osiz + 1 > asiz){
608 asiz = asiz * 2 + osiz;
609 if(!(swap = realloc(buf, asiz))){
610 free(buf);
611 deflateEnd(&zs);
612 return NULL;
613 }
614 buf = swap;
615 }
616 memcpy(buf + bsiz, obuf, osiz);
617 bsiz += osiz;
618 buf[bsiz] = '\0';
619 if(mode == _QDBM_ZMRAW) bsiz++;
620 *sp = bsiz;
621 deflateEnd(&zs);
622 return buf;
623 }
624
625
_qdbm_inflate_impl(const char * ptr,int size,int * sp,int mode)626 static char *_qdbm_inflate_impl(const char *ptr, int size, int *sp, int mode){
627 z_stream zs;
628 char *buf, *swap;
629 unsigned char obuf[ZLIBBUFSIZ];
630 int rv, asiz, bsiz, osiz;
631 zs.zalloc = Z_NULL;
632 zs.zfree = Z_NULL;
633 zs.opaque = Z_NULL;
634 switch(mode){
635 case _QDBM_ZMRAW:
636 if(inflateInit2(&zs, -15) != Z_OK) return NULL;
637 break;
638 case _QDBM_ZMGZIP:
639 if(inflateInit2(&zs, 15 + 16) != Z_OK) return NULL;
640 break;
641 default:
642 if(inflateInit2(&zs, 15) != Z_OK) return NULL;
643 break;
644 }
645 asiz = size * 2 + 16;
646 if(asiz < ZLIBBUFSIZ) asiz = ZLIBBUFSIZ;
647 if(!(buf = malloc(asiz))){
648 inflateEnd(&zs);
649 return NULL;
650 }
651 bsiz = 0;
652 zs.next_in = (unsigned char *)ptr;
653 zs.avail_in = size;
654 zs.next_out = obuf;
655 zs.avail_out = ZLIBBUFSIZ;
656 while((rv = inflate(&zs, Z_NO_FLUSH)) == Z_OK){
657 osiz = ZLIBBUFSIZ - zs.avail_out;
658 if(bsiz + osiz >= asiz){
659 asiz = asiz * 2 + osiz;
660 if(!(swap = realloc(buf, asiz))){
661 free(buf);
662 inflateEnd(&zs);
663 return NULL;
664 }
665 buf = swap;
666 }
667 memcpy(buf + bsiz, obuf, osiz);
668 bsiz += osiz;
669 zs.next_out = obuf;
670 zs.avail_out = ZLIBBUFSIZ;
671 }
672 if(rv != Z_STREAM_END){
673 free(buf);
674 inflateEnd(&zs);
675 return NULL;
676 }
677 osiz = ZLIBBUFSIZ - zs.avail_out;
678 if(bsiz + osiz >= asiz){
679 asiz = asiz * 2 + osiz;
680 if(!(swap = realloc(buf, asiz))){
681 free(buf);
682 inflateEnd(&zs);
683 return NULL;
684 }
685 buf = swap;
686 }
687 memcpy(buf + bsiz, obuf, osiz);
688 bsiz += osiz;
689 buf[bsiz] = '\0';
690 if(sp) *sp = bsiz;
691 inflateEnd(&zs);
692 return buf;
693 }
694
695
_qdbm_getcrc_impl(const char * ptr,int size)696 static unsigned int _qdbm_getcrc_impl(const char *ptr, int size){
697 int crc;
698 if(size < 0) size = strlen(ptr);
699 crc = crc32(0, Z_NULL, 0);
700 return crc32(crc, (unsigned char *)ptr, size);
701 }
702
703
704 #else
705
706
707 char *(*_qdbm_deflate)(const char *, int, int *, int) = NULL;
708 char *(*_qdbm_inflate)(const char *, int, int *, int) = NULL;
709 unsigned int (*_qdbm_getcrc)(const char *, int) = NULL;
710
711
712 #endif
713
714
715
716 /*************************************************************************************************
717 * for LZO
718 *************************************************************************************************/
719
720
721 #if defined(MYLZO)
722
723
724 #include <lzo/lzo1x.h>
725
726
727 static char *_qdbm_lzoencode_impl(const char *ptr, int size, int *sp);
728 static char *_qdbm_lzodecode_impl(const char *ptr, int size, int *sp);
729
730
731 int _qdbm_lzo_init = FALSE;
732 char *(*_qdbm_lzoencode)(const char *, int, int *) = _qdbm_lzoencode_impl;
733 char *(*_qdbm_lzodecode)(const char *, int, int *) = _qdbm_lzodecode_impl;
734
735
_qdbm_lzoencode_impl(const char * ptr,int size,int * sp)736 static char *_qdbm_lzoencode_impl(const char *ptr, int size, int *sp){
737 char wrkmem[LZO1X_1_MEM_COMPRESS];
738 lzo_bytep buf;
739 lzo_uint bsiz;
740 if(!_qdbm_lzo_init){
741 if(lzo_init() != LZO_E_OK) return NULL;
742 _qdbm_lzo_init = TRUE;
743 }
744 if(size < 0) size = strlen(ptr);
745 if(!(buf = malloc(size + size / 16 + 80))) return NULL;
746 if(lzo1x_1_compress((lzo_bytep)ptr, size, buf, &bsiz, wrkmem) != LZO_E_OK){
747 free(buf);
748 return NULL;
749 }
750 buf[bsiz] = '\0';
751 *sp = bsiz;
752 return (char *)buf;
753 }
754
755
_qdbm_lzodecode_impl(const char * ptr,int size,int * sp)756 static char *_qdbm_lzodecode_impl(const char *ptr, int size, int *sp){
757 lzo_bytep buf;
758 lzo_uint bsiz;
759 int rat, rv;
760 if(!_qdbm_lzo_init){
761 if(lzo_init() != LZO_E_OK) return NULL;
762 _qdbm_lzo_init = TRUE;
763 }
764 rat = 6;
765 while(TRUE){
766 bsiz = (size + 256) * rat + 3;
767 if(!(buf = malloc(bsiz + 1))) return NULL;
768 rv = lzo1x_decompress_safe((lzo_bytep)(ptr), size, buf, &bsiz, NULL);
769 if(rv == LZO_E_OK){
770 break;
771 } else if(rv == LZO_E_OUTPUT_OVERRUN){
772 free(buf);
773 rat *= 2;
774 } else {
775 free(buf);
776 return NULL;
777 }
778 }
779 buf[bsiz] = '\0';
780 if(sp) *sp = bsiz;
781 return (char *)buf;
782 }
783
784
785 #else
786
787
788 char *(*_qdbm_lzoencode)(const char *, int, int *) = NULL;
789 char *(*_qdbm_lzodecode)(const char *, int, int *) = NULL;
790
791
792 #endif
793
794
795
796 /*************************************************************************************************
797 * for BZIP2
798 *************************************************************************************************/
799
800
801 #if defined(MYBZIP)
802
803
804 #include <bzlib.h>
805
806 #define BZIPBUFSIZ 8192
807
808
809 static char *_qdbm_bzencode_impl(const char *ptr, int size, int *sp);
810 static char *_qdbm_bzdecode_impl(const char *ptr, int size, int *sp);
811
812
813 char *(*_qdbm_bzencode)(const char *, int, int *) = _qdbm_bzencode_impl;
814 char *(*_qdbm_bzdecode)(const char *, int, int *) = _qdbm_bzdecode_impl;
815
816
_qdbm_bzencode_impl(const char * ptr,int size,int * sp)817 static char *_qdbm_bzencode_impl(const char *ptr, int size, int *sp){
818 bz_stream zs;
819 char *buf, *swap, obuf[BZIPBUFSIZ];
820 int rv, asiz, bsiz, osiz;
821 if(size < 0) size = strlen(ptr);
822 zs.bzalloc = NULL;
823 zs.bzfree = NULL;
824 zs.opaque = NULL;
825 if(BZ2_bzCompressInit(&zs, 9, 0, 30) != BZ_OK) return NULL;
826 asiz = size + 16;
827 if(asiz < BZIPBUFSIZ) asiz = BZIPBUFSIZ;
828 if(!(buf = malloc(asiz))){
829 BZ2_bzCompressEnd(&zs);
830 return NULL;
831 }
832 bsiz = 0;
833 zs.next_in = (char *)ptr;
834 zs.avail_in = size;
835 zs.next_out = obuf;
836 zs.avail_out = BZIPBUFSIZ;
837 while((rv = BZ2_bzCompress(&zs, BZ_FINISH)) == BZ_FINISH_OK){
838 osiz = BZIPBUFSIZ - zs.avail_out;
839 if(bsiz + osiz > asiz){
840 asiz = asiz * 2 + osiz;
841 if(!(swap = realloc(buf, asiz))){
842 free(buf);
843 BZ2_bzCompressEnd(&zs);
844 return NULL;
845 }
846 buf = swap;
847 }
848 memcpy(buf + bsiz, obuf, osiz);
849 bsiz += osiz;
850 zs.next_out = obuf;
851 zs.avail_out = BZIPBUFSIZ;
852 }
853 if(rv != BZ_STREAM_END){
854 free(buf);
855 BZ2_bzCompressEnd(&zs);
856 return NULL;
857 }
858 osiz = BZIPBUFSIZ - zs.avail_out;
859 if(bsiz + osiz + 1 > asiz){
860 asiz = asiz * 2 + osiz;
861 if(!(swap = realloc(buf, asiz))){
862 free(buf);
863 BZ2_bzCompressEnd(&zs);
864 return NULL;
865 }
866 buf = swap;
867 }
868 memcpy(buf + bsiz, obuf, osiz);
869 bsiz += osiz;
870 buf[bsiz] = '\0';
871 *sp = bsiz;
872 BZ2_bzCompressEnd(&zs);
873 return buf;
874 }
875
876
_qdbm_bzdecode_impl(const char * ptr,int size,int * sp)877 static char *_qdbm_bzdecode_impl(const char *ptr, int size, int *sp){
878 bz_stream zs;
879 char *buf, *swap, obuf[BZIPBUFSIZ];
880 int rv, asiz, bsiz, osiz;
881 zs.bzalloc = NULL;
882 zs.bzfree = NULL;
883 zs.opaque = NULL;
884 if(BZ2_bzDecompressInit(&zs, 0, 0) != BZ_OK) return NULL;
885 asiz = size * 2 + 16;
886 if(asiz < BZIPBUFSIZ) asiz = BZIPBUFSIZ;
887 if(!(buf = malloc(asiz))){
888 BZ2_bzDecompressEnd(&zs);
889 return NULL;
890 }
891 bsiz = 0;
892 zs.next_in = (char *)ptr;
893 zs.avail_in = size;
894 zs.next_out = obuf;
895 zs.avail_out = BZIPBUFSIZ;
896 while((rv = BZ2_bzDecompress(&zs)) == BZ_OK){
897 osiz = BZIPBUFSIZ - zs.avail_out;
898 if(bsiz + osiz >= asiz){
899 asiz = asiz * 2 + osiz;
900 if(!(swap = realloc(buf, asiz))){
901 free(buf);
902 BZ2_bzDecompressEnd(&zs);
903 return NULL;
904 }
905 buf = swap;
906 }
907 memcpy(buf + bsiz, obuf, osiz);
908 bsiz += osiz;
909 zs.next_out = obuf;
910 zs.avail_out = BZIPBUFSIZ;
911 }
912 if(rv != BZ_STREAM_END){
913 free(buf);
914 BZ2_bzDecompressEnd(&zs);
915 return NULL;
916 }
917 osiz = BZIPBUFSIZ - zs.avail_out;
918 if(bsiz + osiz >= asiz){
919 asiz = asiz * 2 + osiz;
920 if(!(swap = realloc(buf, asiz))){
921 free(buf);
922 BZ2_bzDecompressEnd(&zs);
923 return NULL;
924 }
925 buf = swap;
926 }
927 memcpy(buf + bsiz, obuf, osiz);
928 bsiz += osiz;
929 buf[bsiz] = '\0';
930 if(sp) *sp = bsiz;
931 BZ2_bzDecompressEnd(&zs);
932 return buf;
933 }
934
935
936 #else
937
938
939 char *(*_qdbm_bzencode)(const char *, int, int *) = NULL;
940 char *(*_qdbm_bzdecode)(const char *, int, int *) = NULL;
941
942
943 #endif
944
945
946
947 /*************************************************************************************************
948 * for ICONV
949 *************************************************************************************************/
950
951
952 #if defined(MYICONV)
953
954
955 #include <iconv.h>
956
957 #define ICONVCHECKSIZ 32768
958 #define ICONVMISSMAX 256
959 #define ICONVALLWRAT 0.001
960
961
962 static char *_qdbm_iconv_impl(const char *ptr, int size,
963 const char *icode, const char *ocode, int *sp, int *mp);
964 static const char *_qdbm_encname_impl(const char *ptr, int size);
965 static int _qdbm_encmiss(const char *ptr, int size, const char *icode, const char *ocode);
966
967
968 char *(*_qdbm_iconv)(const char *, int, const char *, const char *,
969 int *, int *) = _qdbm_iconv_impl;
970 const char *(*_qdbm_encname)(const char *, int) = _qdbm_encname_impl;
971
972
_qdbm_iconv_impl(const char * ptr,int size,const char * icode,const char * ocode,int * sp,int * mp)973 static char *_qdbm_iconv_impl(const char *ptr, int size,
974 const char *icode, const char *ocode, int *sp, int *mp){
975 iconv_t ic;
976 char *obuf, *wp, *rp;
977 size_t isiz, osiz;
978 int miss;
979 if(size < 0) size = strlen(ptr);
980 isiz = size;
981 if((ic = iconv_open(ocode, icode)) == (iconv_t)-1) return NULL;
982 osiz = isiz * 5;
983 if(!(obuf = malloc(osiz + 1))){
984 iconv_close(ic);
985 return NULL;
986 }
987 wp = obuf;
988 rp = (char *)ptr;
989 miss = 0;
990 while(isiz > 0){
991 if(iconv(ic, (void *)&rp, &isiz, &wp, &osiz) == -1){
992 if(errno == EILSEQ && (*rp == 0x5c || *rp == 0x7e)){
993 *wp = *rp;
994 wp++;
995 rp++;
996 isiz--;
997 } else if(errno == EILSEQ || errno == EINVAL){
998 rp++;
999 isiz--;
1000 miss++;
1001 } else {
1002 break;
1003 }
1004 }
1005 }
1006 *wp = '\0';
1007 if(iconv_close(ic) == -1){
1008 free(obuf);
1009 return NULL;
1010 }
1011 if(sp) *sp = wp - obuf;
1012 if(mp) *mp = miss;
1013 return obuf;
1014 }
1015
1016
_qdbm_encname_impl(const char * ptr,int size)1017 static const char *_qdbm_encname_impl(const char *ptr, int size){
1018 const char *hypo;
1019 int i, miss, cr;
1020 if(size < 0) size = strlen(ptr);
1021 if(size > ICONVCHECKSIZ) size = ICONVCHECKSIZ;
1022 if(size >= 2 && (!memcmp(ptr, "\xfe\xff", 2) || !memcmp(ptr, "\xff\xfe", 2))) return "UTF-16";
1023 for(i = 0; i < size - 1; i += 2){
1024 if(ptr[i] == 0 && ptr[i+1] != 0) return "UTF-16BE";
1025 if(ptr[i+1] == 0 && ptr[i] != 0) return "UTF-16LE";
1026 }
1027 for(i = 0; i < size - 3; i++){
1028 if(ptr[i] == 0x1b){
1029 i++;
1030 if(ptr[i] == '(' && strchr("BJHI", ptr[i+1])) return "ISO-2022-JP";
1031 if(ptr[i] == '$' && strchr("@B(", ptr[i+1])) return "ISO-2022-JP";
1032 }
1033 }
1034 if(_qdbm_encmiss(ptr, size, "US-ASCII", "UTF-16BE") < 1) return "US-ASCII";
1035 if(_qdbm_encmiss(ptr, size, "UTF-8", "UTF-16BE") < 1) return "UTF-8";
1036 hypo = NULL;
1037 cr = FALSE;
1038 for(i = 0; i < size; i++){
1039 if(ptr[i] == 0xd){
1040 cr = TRUE;
1041 break;
1042 }
1043 }
1044 if(cr){
1045 if((miss = _qdbm_encmiss(ptr, size, "Shift_JIS", "EUC-JP")) < 1) return "Shift_JIS";
1046 if(!hypo && miss / (double)size <= ICONVALLWRAT) hypo = "Shift_JIS";
1047 if((miss = _qdbm_encmiss(ptr, size, "EUC-JP", "UTF-16BE")) < 1) return "EUC-JP";
1048 if(!hypo && miss / (double)size <= ICONVALLWRAT) hypo = "EUC-JP";
1049 } else {
1050 if((miss = _qdbm_encmiss(ptr, size, "EUC-JP", "UTF-16BE")) < 1) return "EUC-JP";
1051 if(!hypo && miss / (double)size <= ICONVALLWRAT) hypo = "EUC-JP";
1052 if((miss = _qdbm_encmiss(ptr, size, "Shift_JIS", "EUC-JP")) < 1) return "Shift_JIS";
1053 if(!hypo && miss / (double)size <= ICONVALLWRAT) hypo = "Shift_JIS";
1054 }
1055 if((miss = _qdbm_encmiss(ptr, size, "UTF-8", "UTF-16BE")) < 1) return "UTF-8";
1056 if(!hypo && miss / (double)size <= ICONVALLWRAT) hypo = "UTF-8";
1057 if((miss = _qdbm_encmiss(ptr, size, "CP932", "UTF-16BE")) < 1) return "CP932";
1058 if(!hypo && miss / (double)size <= ICONVALLWRAT) hypo = "CP932";
1059 return hypo ? hypo : "ISO-8859-1";
1060 }
1061
1062
_qdbm_encmiss(const char * ptr,int size,const char * icode,const char * ocode)1063 static int _qdbm_encmiss(const char *ptr, int size, const char *icode, const char *ocode){
1064 iconv_t ic;
1065 char obuf[ICONVCHECKSIZ], *wp, *rp;
1066 size_t isiz, osiz;
1067 int miss;
1068 isiz = size;
1069 if((ic = iconv_open(ocode, icode)) == (iconv_t)-1) return ICONVMISSMAX;
1070 miss = 0;
1071 rp = (char *)ptr;
1072 while(isiz > 0){
1073 osiz = ICONVCHECKSIZ;
1074 wp = obuf;
1075 if(iconv(ic, (void *)&rp, &isiz, &wp, &osiz) == -1){
1076 if(errno == EILSEQ || errno == EINVAL){
1077 rp++;
1078 isiz--;
1079 miss++;
1080 if(miss >= ICONVMISSMAX) break;
1081 } else {
1082 break;
1083 }
1084 }
1085 }
1086 if(iconv_close(ic) == -1) return ICONVMISSMAX;
1087 return miss;
1088 }
1089
1090
1091 #else
1092
1093
1094 char *(*_qdbm_iconv)(const char *, int, const char *, const char *, int *, int *) = NULL;
1095 const char *(*_qdbm_encname)(const char *, int) = NULL;
1096
1097
1098 #endif
1099
1100
1101
1102 /*************************************************************************************************
1103 * common settings
1104 *************************************************************************************************/
1105
1106
_qdbm_dummyfunc(void)1107 int _qdbm_dummyfunc(void){
1108 return 0;
1109 }
1110
1111
1112
1113 /* END OF FILE */
1114