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