1 /* $Id: cdb_init.c,v 1.9 2003/11/03 21:42:20 mjt Exp $
2 * cdb_init, cdb_free and cdb_read routines
4 * This file is a part of tinycdb package by Michael Tokarev, mjt@corpit.ru.
10 #include <sys/types.h>
12 # include <sys/mman.h>
14 # include "safeunistd.h"
18 # include "safewindows.h"
20 #include "safesysstat.h"
27 cdb_init(struct cdb
*cdbp
, int fd
)
34 HANDLE hFile
, hMapping
;
42 if (fstat(fd
, &st
) < 0)
44 /* trivial sanity check: at least toc should be here */
45 if (st
.st_size
< 2048)
46 return errno
= EPROTO
, -1;
47 fsize
= (unsigned)(st
.st_size
& 0xffffffffu
);
51 hFile
= (HANDLE
) _get_osfhandle(fd
);
52 if(hFile
== (HANDLE
) -1) return -1;
53 hMapping
= CreateFileMapping(hFile
, NULL
, PAGE_READONLY
, 0, 0, NULL
);
54 if (!hMapping
) return -1;
55 mem
= (unsigned char *)MapViewOfFile(hMapping
, FILE_MAP_READ
, 0, 0, 0);
58 // No mmap, so take the very crude approach of malloc and read the whole file in!
59 if ((mem
= (unsigned char *)malloc(fsize
)) == NULL
)
64 ssize_t n
= read(fd
, (void*)p
, size
);
72 mem
= (unsigned char *)mmap(NULL
, fsize
, PROT_READ
, MAP_SHARED
, fd
, 0);
73 if (mem
== (unsigned char *)-1)
78 cdbp
->cdb_fsize
= fsize
;
82 /* XXX don't know well about madvise syscall -- is it legal
83 to set different options for parts of one mmap() region?
84 There is also posix_madvise() exist, with POSIX_MADV_RANDOM etc...
87 /* set madvise() parameters. Ignore errors for now if system
89 madvise(mem
, 2048, MADV_WILLNEED
);
90 madvise(mem
+ 2048, cdbp
->cdb_fsize
- 2048, MADV_RANDOM
);
94 cdbp
->cdb_vpos
= cdbp
->cdb_vlen
= 0;
95 cdbp
->cdb_kpos
= cdbp
->cdb_klen
= 0;
96 dend
= cdb_unpack(mem
);
97 if (dend
< 2048) dend
= 2048;
98 else if (dend
>= fsize
) dend
= fsize
;
99 cdbp
->cdb_dend
= dend
;
105 class VoidStarOrCharStar
{
108 VoidStarOrCharStar(const void *p_
) : p(const_cast<void*>(p_
)) { }
109 VoidStarOrCharStar(const char *p_
) : p(const_cast<char*>(p_
)) { }
110 operator void*() { return p
; }
111 operator char*() { return static_cast<char*>(p
); }
116 cdb_free(struct cdb
*cdbp
)
120 HANDLE hFile
, hMapping
;
125 void * p
= const_cast<void*>((const void*)cdbp
->cdb_mem
);
127 void * p
= (void*)cdbp
->cdb_mem
;
130 hFile
= (HANDLE
) _get_osfhandle(cdbp
->cdb_fd
);
131 hMapping
= CreateFileMapping(hFile
, NULL
, PAGE_READONLY
, 0, 0, NULL
);
133 CloseHandle(hMapping
);
139 /* Solaris sys/mman.h defines munmap as taking char* unless __STDC__ is
140 * defined (which it isn't in C++).
142 VoidStarOrCharStar
p(cdbp
->cdb_mem
);
144 void * p
= (void*)cdbp
->cdb_mem
;
146 munmap(p
, cdbp
->cdb_fsize
);
148 cdbp
->cdb_mem
= NULL
;
154 cdb_get(const struct cdb
*cdbp
, unsigned len
, unsigned pos
)
156 if (pos
> cdbp
->cdb_fsize
|| cdbp
->cdb_fsize
- pos
< len
) {
160 return cdbp
->cdb_mem
+ pos
;
164 cdb_read(const struct cdb
*cdbp
, void *buf
, unsigned len
, unsigned pos
)
166 const void *data
= cdb_get(cdbp
, len
, pos
);
167 if (!data
) return -1;
168 memcpy(buf
, data
, len
);