[ci] Test Tcl bindings for dragonfly/freebsd
[xapian.git] / xapian-applications / omega / cdb_init.cc
blob1784cc650488d90aa6a45f965e961649378e9b0e
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.
5 * Public domain.
6 */
8 #include <config.h>
10 #include <sys/types.h>
11 #ifdef HAVE_MMAP
12 # include <sys/mman.h>
13 #else
14 # include "safeunistd.h"
15 # include <cstdlib>
16 #endif
17 #ifdef __WIN32__
18 # include "safewindows.h"
19 #endif
20 #include "safesysstat.h"
21 #include "cdb_int.h"
22 #include <cstring>
24 using namespace std;
26 int
27 cdb_init(struct cdb *cdbp, int fd)
29 struct stat st;
30 unsigned char *mem;
31 unsigned fsize, dend;
32 #ifndef HAVE_MMAP
33 #ifdef _WIN32
34 HANDLE hFile, hMapping;
35 #else
36 size_t size;
37 unsigned char *p;
38 #endif
39 #endif
41 /* get file size */
42 if (fstat(fd, &st) < 0)
43 return -1;
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);
48 /* memory-map file */
49 #ifndef HAVE_MMAP
50 #ifdef _WIN32
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);
56 if (!ret) return -1;
57 mem = static_cast<unsigned char *>(ret);
58 #else
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)
61 return -1;
62 size = fsize;
63 p = mem;
64 while (size > 0) {
65 ssize_t n = read(fd, (void*)p, size);
66 if (n == -1)
67 return -1;
68 p += n;
69 size -= n;
71 #endif
72 #else
73 void * ret = mmap(NULL, fsize, PROT_READ, MAP_SHARED, fd, 0);
74 if (ret == reinterpret_cast<void *>(-1))
75 return -1;
76 mem = static_cast<unsigned char *>(ret);
77 #endif /* _WIN32 */
79 cdbp->cdb_fd = fd;
80 cdbp->cdb_fsize = fsize;
81 cdbp->cdb_mem = mem;
83 #if 0
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...
88 #ifdef MADV_RANDOM
89 /* set madvise() parameters. Ignore errors for now if system
90 doesn't support it */
91 madvise(mem, 2048, MADV_WILLNEED);
92 madvise(mem + 2048, cdbp->cdb_fsize - 2048, MADV_RANDOM);
93 #endif
94 #endif
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;
103 return 0;
106 #ifdef __cplusplus
107 class VoidStarOrCharStar {
108 void *p;
109 public:
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); }
115 #endif
117 void
118 cdb_free(struct cdb *cdbp)
120 if (cdbp->cdb_mem) {
121 #ifdef _WIN32
122 HANDLE hFile, hMapping;
123 #endif
125 #ifndef HAVE_MMAP
126 #ifdef __cplusplus
127 void * p = const_cast<void*>((const void*)cdbp->cdb_mem);
128 #else
129 void * p = (void*)cdbp->cdb_mem;
130 #endif
131 #ifdef _WIN32
132 hFile = (HANDLE) _get_osfhandle(cdbp->cdb_fd);
133 hMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
134 UnmapViewOfFile(p);
135 CloseHandle(hMapping);
136 #else
137 free(p);
138 #endif
139 #else
140 #ifdef __cplusplus
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);
145 #else
146 void * p = (void*)cdbp->cdb_mem;
147 #endif
148 munmap(p, cdbp->cdb_fsize);
149 #endif /* _WIN32 */
150 cdbp->cdb_mem = NULL;
152 cdbp->cdb_fsize = 0;
155 const void *
156 cdb_get(const struct cdb *cdbp, unsigned len, unsigned pos)
158 if (pos > cdbp->cdb_fsize || cdbp->cdb_fsize - pos < len) {
159 errno = EPROTO;
160 return NULL;
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);
171 return 0;