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 LPVOID ret
= MapViewOfFile(hMapping
, FILE_MAP_READ
, 0, 0, 0);
57 mem
= static_cast<unsigned char *>(ret
);
59 // No mmap, so take the very crude approach of malloc and read the whole file in!
60 if ((mem
= static_cast<unsigned char *>(malloc(fsize
))) == NULL
)
65 ssize_t n
= read(fd
, (void*)p
, size
);
73 void * ret
= mmap(NULL
, fsize
, PROT_READ
, MAP_SHARED
, fd
, 0);
74 if (ret
== reinterpret_cast<void *>(-1))
76 mem
= static_cast<unsigned char *>(ret
);
80 cdbp
->cdb_fsize
= fsize
;
84 /* XXX don't know well about madvise syscall -- is it legal
85 to set different options for parts of one mmap() region?
86 There is also posix_madvise() exist, with POSIX_MADV_RANDOM etc...
89 /* set madvise() parameters. Ignore errors for now if system
91 madvise(mem
, 2048, MADV_WILLNEED
);
92 madvise(mem
+ 2048, cdbp
->cdb_fsize
- 2048, MADV_RANDOM
);
96 cdbp
->cdb_vpos
= cdbp
->cdb_vlen
= 0;
97 cdbp
->cdb_kpos
= cdbp
->cdb_klen
= 0;
98 dend
= cdb_unpack(mem
);
99 if (dend
< 2048) dend
= 2048;
100 else if (dend
>= fsize
) dend
= fsize
;
101 cdbp
->cdb_dend
= dend
;
107 class VoidStarOrCharStar
{
110 VoidStarOrCharStar(const void *p_
) : p(const_cast<void*>(p_
)) { }
111 VoidStarOrCharStar(const char *p_
) : p(const_cast<char*>(p_
)) { }
112 operator void*() { return p
; }
113 operator char*() { return static_cast<char*>(p
); }
118 cdb_free(struct cdb
*cdbp
)
122 HANDLE hFile
, hMapping
;
127 void * p
= const_cast<void*>((const void*)cdbp
->cdb_mem
);
129 void * p
= (void*)cdbp
->cdb_mem
;
132 hFile
= (HANDLE
) _get_osfhandle(cdbp
->cdb_fd
);
133 hMapping
= CreateFileMapping(hFile
, NULL
, PAGE_READONLY
, 0, 0, NULL
);
135 CloseHandle(hMapping
);
141 /* Solaris sys/mman.h defines munmap as taking char* unless __STDC__ is
142 * defined (which it isn't in C++).
144 VoidStarOrCharStar
p(cdbp
->cdb_mem
);
146 void * p
= (void*)cdbp
->cdb_mem
;
148 munmap(p
, cdbp
->cdb_fsize
);
150 cdbp
->cdb_mem
= NULL
;
156 cdb_get(const struct cdb
*cdbp
, unsigned len
, unsigned pos
)
158 if (pos
> cdbp
->cdb_fsize
|| cdbp
->cdb_fsize
- pos
< len
) {
162 return cdbp
->cdb_mem
+ pos
;
166 cdb_read(const struct cdb
*cdbp
, void *buf
, unsigned len
, unsigned pos
)
168 const void *data
= cdb_get(cdbp
, len
, pos
);
169 if (!data
) return -1;
170 memcpy(buf
, data
, len
);