File: cdb_init.cc

package info (click to toggle)
xapian-omega 1.0.7-3+lenny2
  • links: PTS
  • area: main
  • in suites: lenny
  • size: 2,424 kB
  • ctags: 744
  • sloc: sh: 9,112; cpp: 7,954; makefile: 245; perl: 119
file content (167 lines) | stat: -rw-r--r-- 3,920 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
/* $Id: cdb_init.c,v 1.9 2003/11/03 21:42:20 mjt Exp $
 * cdb_init, cdb_free and cdb_read routines
 *
 * This file is a part of tinycdb package by Michael Tokarev, mjt@corpit.ru.
 * Public domain.
 */

#include <config.h>

#include <sys/types.h>
#ifdef HAVE_MMAP
# include <sys/mman.h>
#else
# include "safeunistd.h"
# include <stdlib.h>
#endif
#ifdef __WIN32__
# include "safewindows.h"
#endif
#include "safesysstat.h"
#include "cdb_int.h"

int
cdb_init(struct cdb *cdbp, int fd)
{
  struct stat st;
  unsigned char *mem;
  unsigned fsize, dend;
#ifndef HAVE_MMAP
#ifdef _WIN32
  HANDLE hFile, hMapping;
#else
  size_t size;
  unsigned char *p;
#endif
#endif

  /* get file size */
  if (fstat(fd, &st) < 0)
    return -1;
  /* trivial sanity check: at least toc should be here */
  if (st.st_size < 2048)
    return errno = EPROTO, -1;
  fsize = (unsigned)(st.st_size & 0xffffffffu);
  /* memory-map file */
#ifndef HAVE_MMAP
#ifdef _WIN32
  hFile = (HANDLE) _get_osfhandle(fd);
  if(hFile == (HANDLE) -1) return -1;
  hMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
  if (!hMapping) return -1;
  mem = (unsigned char *)MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
  if (!mem) return -1;
#else
  // No mmap, so take the very crude approach of malloc and read the whole file in!
  if ((mem = (unsigned char *)malloc(fsize)) == NULL)
    return -1;
  size = fsize;
  p = mem;
  while (size > 0) {
    ssize_t n = read(fd, (void*)p, size);
    if (n == -1)
      return -1;
    p += n;
    size -= n;
  }
#endif
#else
  mem = (unsigned char *)mmap(NULL, fsize, PROT_READ, MAP_SHARED, fd, 0);
  if (mem == (unsigned char *)-1)
    return -1;
#endif /* _WIN32 */

  cdbp->cdb_fd = fd;
  cdbp->cdb_fsize = fsize;
  cdbp->cdb_mem = mem;

#if 0
  /* XXX don't know well about madvise syscall -- is it legal
     to set different options for parts of one mmap() region?
     There is also posix_madvise() exist, with POSIX_MADV_RANDOM etc...
  */
#ifdef MADV_RANDOM
  /* set madvise() parameters. Ignore errors for now if system
     doesn't support it */
  madvise(mem, 2048, MADV_WILLNEED);
  madvise(mem + 2048, cdbp->cdb_fsize - 2048, MADV_RANDOM);
#endif
#endif

  cdbp->cdb_vpos = cdbp->cdb_vlen = 0;
  cdbp->cdb_kpos = cdbp->cdb_klen = 0;
  dend = cdb_unpack(mem);
  if (dend < 2048) dend = 2048;
  else if (dend >= fsize) dend = fsize;
  cdbp->cdb_dend = dend;

  return 0;
}

#ifdef __cplusplus
class VoidStarOrCharStar {
    void *p;
  public:
    VoidStarOrCharStar(const void *p_) : p(const_cast<void*>(p_)) { }
    VoidStarOrCharStar(const char *p_) : p(const_cast<char*>(p_)) { }
    operator void*() { return p; }
    operator char*() { return (char*)p; }
};
#endif

void
cdb_free(struct cdb *cdbp)
{
  if (cdbp->cdb_mem) {
#ifdef _WIN32
    HANDLE hFile, hMapping;
#endif

#ifndef HAVE_MMAP
#ifdef __cplusplus
    void * p = const_cast<void*>((const void*)cdbp->cdb_mem);
#else
    void * p = (void*)cdbp->cdb_mem;
#endif
#ifdef _WIN32
    hFile = (HANDLE) _get_osfhandle(cdbp->cdb_fd);
    hMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
    UnmapViewOfFile(p);
    CloseHandle(hMapping);
#else
    free(p);
#endif
#else
#ifdef __cplusplus
    /* Solaris sys/mman.h defines munmap as taking char* unless __STDC__ is
     * defined (which it isn't in C++).
     */
    VoidStarOrCharStar p(cdbp->cdb_mem);
#else
    void * p = (void*)cdbp->cdb_mem;
#endif
    munmap(p, cdbp->cdb_fsize);
#endif /* _WIN32 */
    cdbp->cdb_mem = NULL;
  }
  cdbp->cdb_fsize = 0;
}

const void *
cdb_get(const struct cdb *cdbp, unsigned len, unsigned pos)
{
  if (pos > cdbp->cdb_fsize || cdbp->cdb_fsize - pos < len) {
    errno = EPROTO;
    return NULL;
  }
  return cdbp->cdb_mem + pos;
}

int
cdb_read(const struct cdb *cdbp, void *buf, unsigned len, unsigned pos)
{
  const void *data = cdb_get(cdbp, len, pos);
  if (!data) return -1;
  memcpy(buf, data, len);
  return 0;
}