/src/mdbtools/src/libmdb/map.c
Line | Count | Source |
1 | | /* MDB Tools - A library for reading MS Access database file |
2 | | * Copyright (C) 2000 Brian Bruns |
3 | | * |
4 | | * This library is free software; you can redistribute it and/or |
5 | | * modify it under the terms of the GNU Library General Public |
6 | | * License as published by the Free Software Foundation; either |
7 | | * version 2 of the License, or (at your option) any later version. |
8 | | * |
9 | | * This library is distributed in the hope that it will be useful, |
10 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
12 | | * Library General Public License for more details. |
13 | | * |
14 | | * You should have received a copy of the GNU Library General Public |
15 | | * License along with this library; if not, write to the Free Software |
16 | | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
17 | | */ |
18 | | |
19 | | #include "mdbtools.h" |
20 | | |
21 | | static gint32 |
22 | | mdb_map_find_next0(MdbHandle *mdb, unsigned char *map, unsigned int map_sz, guint32 start_pg) |
23 | 8.08k | { |
24 | 8.08k | guint32 pgnum, i, usage_bitlen; |
25 | 8.08k | unsigned char *usage_bitmap; |
26 | | |
27 | 8.08k | if (map_sz < 5) { |
28 | 94 | return 0; |
29 | 94 | } |
30 | | |
31 | 7.99k | pgnum = mdb_get_int32(map, 1); |
32 | 7.99k | usage_bitmap = map + 5; |
33 | 7.99k | usage_bitlen = (map_sz - 5) * 8; |
34 | | |
35 | 7.99k | i = (start_pg >= pgnum) ? start_pg-pgnum+1 : 0; |
36 | 3.61M | for (; i<usage_bitlen; i++) { |
37 | 3.61M | if (usage_bitmap[i/8] & (1 << (i%8))) { |
38 | 7.80k | return pgnum + i; |
39 | 7.80k | } |
40 | 3.61M | } |
41 | | /* didn't find anything */ |
42 | 191 | return 0; |
43 | 7.99k | } |
44 | | static gint32 |
45 | | mdb_map_find_next1(MdbHandle *mdb, unsigned char *map, unsigned int map_sz, guint32 start_pg) |
46 | 6.15k | { |
47 | 6.15k | guint32 map_ind, max_map_pgs, offset, usage_bitlen; |
48 | | |
49 | | /* |
50 | | * start_pg will tell us where to (re)start the scan |
51 | | * for the next data page. each usage_map entry points to a |
52 | | * 0x05 page which bitmaps (mdb->fmt->pg_size - 4) * 8 pages. |
53 | | * |
54 | | * map_ind gives us the starting usage_map entry |
55 | | * offset gives us a page offset into the bitmap |
56 | | */ |
57 | 6.15k | usage_bitlen = (mdb->fmt->pg_size - 4) * 8; |
58 | 6.15k | max_map_pgs = (map_sz - 1) / 4; |
59 | 6.15k | map_ind = (start_pg + 1) / usage_bitlen; |
60 | 6.15k | offset = (start_pg + 1) % usage_bitlen; |
61 | | |
62 | 8.50k | for (; map_ind<max_map_pgs; map_ind++) { |
63 | 8.49k | unsigned char *usage_bitmap; |
64 | 8.49k | guint32 i, map_pg; |
65 | | |
66 | 8.49k | if (!(map_pg = mdb_get_int32(map, (map_ind*4)+1))) { |
67 | 2.03k | continue; |
68 | 2.03k | } |
69 | 6.45k | if(mdb_read_alt_pg(mdb, map_pg) != mdb->fmt->pg_size) { |
70 | 2.89k | fprintf(stderr, "Oops! didn't get a full page at %d\n", map_pg); |
71 | 2.89k | return -1; |
72 | 2.89k | } |
73 | | |
74 | 3.56k | usage_bitmap = mdb->alt_pg_buf + 4; |
75 | 9.99M | for (i=offset; i<usage_bitlen; i++) { |
76 | 9.99M | if (usage_bitmap[i/8] & (1 << (i%8))) { |
77 | 3.25k | return map_ind*usage_bitlen + i; |
78 | 3.25k | } |
79 | 9.99M | } |
80 | 309 | offset = 0; |
81 | 309 | } |
82 | | /* didn't find anything */ |
83 | 4 | return 0; |
84 | 6.15k | } |
85 | | |
86 | | /* returns 0 on EOF */ |
87 | | /* returns -1 on error (unsupported map type) */ |
88 | | gint32 |
89 | | mdb_map_find_next(MdbHandle *mdb, unsigned char *map, unsigned int map_sz, guint32 start_pg) |
90 | 26.1k | { |
91 | 26.1k | if (map[0] == 0) { |
92 | 8.08k | return mdb_map_find_next0(mdb, map, map_sz, start_pg); |
93 | 18.1k | } else if (map[0] == 1) { |
94 | 6.15k | return mdb_map_find_next1(mdb, map, map_sz, start_pg); |
95 | 6.15k | } |
96 | | |
97 | 11.9k | fprintf(stderr, "Warning: unrecognized usage map type: %d\n", map[0]); |
98 | 11.9k | return -1; |
99 | 26.1k | } |
100 | | gint32 |
101 | | mdb_alloc_page(MdbTableDef *table) |
102 | 0 | { |
103 | 0 | printf("Allocating new page\n"); |
104 | 0 | return 0; |
105 | 0 | } |
106 | | gint32 |
107 | | mdb_map_find_next_freepage(MdbTableDef *table, int row_size) |
108 | 0 | { |
109 | 0 | MdbCatalogEntry *entry = table->entry; |
110 | 0 | MdbHandle *mdb = entry->mdb; |
111 | 0 | gint32 pgnum; |
112 | 0 | guint32 cur_pg = 0; |
113 | 0 | int free_space; |
114 | |
|
115 | 0 | do { |
116 | 0 | pgnum = mdb_map_find_next(mdb, |
117 | 0 | table->free_usage_map, |
118 | 0 | table->freemap_sz, cur_pg); |
119 | | //printf("looking at page %d\n", pgnum); |
120 | 0 | if (!pgnum) { |
121 | | /* allocate new page */ |
122 | 0 | return mdb_alloc_page(table); |
123 | 0 | } else if (pgnum==-1) { |
124 | 0 | fprintf(stderr, "Error: mdb_map_find_next_freepage error while reading maps.\n"); |
125 | 0 | return -1; |
126 | 0 | } |
127 | 0 | cur_pg = pgnum; |
128 | |
|
129 | 0 | mdb_read_pg(mdb, pgnum); |
130 | 0 | free_space = mdb_pg_get_freespace(mdb); |
131 | | |
132 | 0 | } while (free_space < row_size); |
133 | | |
134 | | //printf("page %d has %d bytes left\n", pgnum, free_space); |
135 | | |
136 | 0 | return pgnum; |
137 | 0 | } |