Branch data Line data Source code
1 : : /* cdb_init.c: cdb_init, cdb_free and cdb_read routines
2 : : *
3 : : * This file is a part of tinycdb package.
4 : : * Copyright (C) 2001-2023 Michael Tokarev <mjt+cdb@corpit.ru>
5 : : *
6 : : * Permission is hereby granted, free of charge, to any person obtaining a
7 : : * copy of this software and associated documentation files (the "Software"),
8 : : * to deal in the Software without restriction, including without limitation
9 : : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 : : * and/or sell copies of the Software, and to permit persons to whom the
11 : : * Software is furnished to do so, subject to the following conditions:
12 : : *
13 : : * The above copyright notice and this permission notice shall be included
14 : : * in all copies or substantial portions of the Software.
15 : : *
16 : : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 : : * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 : : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 : : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 : : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 : : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 : : * DEALINGS IN THE SOFTWARE.
23 : : */
24 : :
25 : : #include <sys/types.h>
26 : : #ifdef _WIN32
27 : : # include <windows.h>
28 : : #else
29 : : # include <sys/mman.h>
30 : : # ifndef MAP_FAILED
31 : : # define MAP_FAILED ((void*)-1)
32 : : # endif
33 : : #endif
34 : : #include <sys/stat.h>
35 : : #include "cdb_int.h"
36 : :
37 : : int
38 : 0 : cdb_init(struct cdb *cdbp, int fd)
39 : : {
40 : : struct stat st;
41 : : unsigned char *mem;
42 : : unsigned fsize, dend;
43 : : #ifdef _WIN32
44 : : HANDLE hFile, hMapping;
45 : : #endif
46 : :
47 : : /* get file size */
48 [ # # ]: 0 : if (fstat(fd, &st) < 0)
49 : 0 : return -1;
50 : : /* trivial sanity check: at least toc should be here */
51 [ # # ]: 0 : if (st.st_size < 2048)
52 : 0 : return errno = EPROTO, -1;
53 : 0 : fsize = st.st_size < 0xffffffffu ? st.st_size : 0xffffffffu;
54 : : /* memory-map file */
55 : : #ifdef _WIN32
56 : : hFile = (HANDLE) _get_osfhandle(fd);
57 : : if (hFile == (HANDLE) -1)
58 : : return -1;
59 : : hMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
60 : : if (!hMapping)
61 : : return -1;
62 : : mem = (unsigned char *)MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
63 : : CloseHandle(hMapping);
64 : : if (!mem)
65 : : return -1;
66 : : #else
67 : 0 : mem = (unsigned char*)mmap(NULL, fsize, PROT_READ, MAP_SHARED, fd, 0);
68 [ # # ]: 0 : if (mem == MAP_FAILED)
69 : 0 : return -1;
70 : : #endif /* _WIN32 */
71 : :
72 : 0 : cdbp->cdb_fd = fd;
73 : 0 : cdbp->cdb_fsize = fsize;
74 : 0 : cdbp->cdb_mem = mem;
75 : :
76 : : #if 0
77 : : /* XXX don't know well about madvise syscall -- is it legal
78 : : to set different options for parts of one mmap() region?
79 : : There is also posix_madvise() exist, with POSIX_MADV_RANDOM etc...
80 : : */
81 : : #ifdef MADV_RANDOM
82 : : /* set madvise() parameters. Ignore errors for now if system
83 : : doesn't support it */
84 : : madvise(mem, 2048, MADV_WILLNEED);
85 : : madvise(mem + 2048, cdbp->cdb_fsize - 2048, MADV_RANDOM);
86 : : #endif
87 : : #endif
88 : :
89 : 0 : cdbp->cdb_vpos = cdbp->cdb_vlen = 0;
90 : 0 : cdbp->cdb_kpos = cdbp->cdb_klen = 0;
91 : 0 : dend = cdb_unpack(mem);
92 [ # # ]: 0 : if (dend < 2048) dend = 2048;
93 [ # # ]: 0 : else if (dend >= fsize) dend = fsize;
94 : 0 : cdbp->cdb_dend = dend;
95 : :
96 : 0 : return 0;
97 : : }
98 : :
99 : : void
100 : 0 : cdb_free(struct cdb *cdbp)
101 : : {
102 [ # # ]: 0 : if (cdbp->cdb_mem) {
103 : : #ifdef _WIN32
104 : : UnmapViewOfFile((void*) cdbp->cdb_mem);
105 : : #else
106 : 0 : munmap((void*)cdbp->cdb_mem, cdbp->cdb_fsize);
107 : : #endif /* _WIN32 */
108 : 0 : cdbp->cdb_mem = NULL;
109 : : }
110 : 0 : cdbp->cdb_fsize = 0;
111 : 0 : }
112 : :
113 : : const void *
114 : 0 : cdb_get(const struct cdb *cdbp, unsigned len, unsigned pos)
115 : : {
116 [ # # # # ]: 0 : if (pos > cdbp->cdb_fsize || cdbp->cdb_fsize - pos < len) {
117 : 0 : errno = EPROTO;
118 : 0 : return NULL;
119 : : }
120 : 0 : return cdbp->cdb_mem + pos;
121 : : }
122 : :
123 : : int
124 : 0 : cdb_read(const struct cdb *cdbp, void *buf, unsigned len, unsigned pos)
125 : : {
126 : 0 : const void *data = cdb_get(cdbp, len, pos);
127 [ # # ]: 0 : if (!data) return -1;
128 : 0 : memcpy(buf, data, len);
129 : 0 : return 0;
130 : : }
|