Coverage Report

Created: 2026-11-12 07:14

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
}