1 |
1275 |
phoenix |
/*
|
2 |
|
|
* linux/fs/hpfs/map.c
|
3 |
|
|
*
|
4 |
|
|
* Mikulas Patocka (mikulas@artax.karlin.mff.cuni.cz), 1998-1999
|
5 |
|
|
*
|
6 |
|
|
* mapping structures to memory with some minimal checks
|
7 |
|
|
*/
|
8 |
|
|
|
9 |
|
|
#include "hpfs_fn.h"
|
10 |
|
|
|
11 |
|
|
unsigned *hpfs_map_dnode_bitmap(struct super_block *s, struct quad_buffer_head *qbh)
|
12 |
|
|
{
|
13 |
|
|
return hpfs_map_4sectors(s, s->s_hpfs_dmap, qbh, 0);
|
14 |
|
|
}
|
15 |
|
|
|
16 |
|
|
unsigned int *hpfs_map_bitmap(struct super_block *s, unsigned bmp_block,
|
17 |
|
|
struct quad_buffer_head *qbh, char *id)
|
18 |
|
|
{
|
19 |
|
|
secno sec;
|
20 |
|
|
if (s->s_hpfs_chk) if (bmp_block * 16384 > s->s_hpfs_fs_size) {
|
21 |
|
|
hpfs_error(s, "hpfs_map_bitmap called with bad parameter: %08x at %s", bmp_block, id);
|
22 |
|
|
return NULL;
|
23 |
|
|
}
|
24 |
|
|
sec = s->s_hpfs_bmp_dir[bmp_block];
|
25 |
|
|
if (!sec || sec > s->s_hpfs_fs_size-4) {
|
26 |
|
|
hpfs_error(s, "invalid bitmap block pointer %08x -> %08x at %s", bmp_block, sec, id);
|
27 |
|
|
return NULL;
|
28 |
|
|
}
|
29 |
|
|
return hpfs_map_4sectors(s, sec, qbh, 4);
|
30 |
|
|
}
|
31 |
|
|
|
32 |
|
|
/*
|
33 |
|
|
* Load first code page into kernel memory, return pointer to 256-byte array,
|
34 |
|
|
* first 128 bytes are uppercasing table for chars 128-255, next 128 bytes are
|
35 |
|
|
* lowercasing table
|
36 |
|
|
*/
|
37 |
|
|
|
38 |
|
|
char *hpfs_load_code_page(struct super_block *s, secno cps)
|
39 |
|
|
{
|
40 |
|
|
struct buffer_head *bh;
|
41 |
|
|
secno cpds;
|
42 |
|
|
unsigned cpi;
|
43 |
|
|
unsigned char *ptr;
|
44 |
|
|
unsigned char *cp_table;
|
45 |
|
|
int i;
|
46 |
|
|
struct code_page_data *cpd;
|
47 |
|
|
struct code_page_directory *cp = hpfs_map_sector(s, cps, &bh, 0);
|
48 |
|
|
if (!cp) return NULL;
|
49 |
|
|
if (cp->magic != CP_DIR_MAGIC) {
|
50 |
|
|
printk("HPFS: Code page directory magic doesn't match (magic = %08x)\n", cp->magic);
|
51 |
|
|
brelse(bh);
|
52 |
|
|
return NULL;
|
53 |
|
|
}
|
54 |
|
|
if (!cp->n_code_pages) {
|
55 |
|
|
printk("HPFS: n_code_pages == 0\n");
|
56 |
|
|
brelse(bh);
|
57 |
|
|
return NULL;
|
58 |
|
|
}
|
59 |
|
|
cpds = cp->array[0].code_page_data;
|
60 |
|
|
cpi = cp->array[0].index;
|
61 |
|
|
brelse(bh);
|
62 |
|
|
|
63 |
|
|
if (cpi >= 3) {
|
64 |
|
|
printk("HPFS: Code page index out of array\n");
|
65 |
|
|
return NULL;
|
66 |
|
|
}
|
67 |
|
|
|
68 |
|
|
if (!(cpd = hpfs_map_sector(s, cpds, &bh, 0))) return NULL;
|
69 |
|
|
if ((unsigned)cpd->offs[cpi] > 0x178) {
|
70 |
|
|
printk("HPFS: Code page index out of sector\n");
|
71 |
|
|
brelse(bh);
|
72 |
|
|
return NULL;
|
73 |
|
|
}
|
74 |
|
|
ptr = (char *)cpd + cpd->offs[cpi] + 6;
|
75 |
|
|
if (!(cp_table = kmalloc(256, GFP_KERNEL))) {
|
76 |
|
|
printk("HPFS: out of memory for code page table\n");
|
77 |
|
|
brelse(bh);
|
78 |
|
|
return NULL;
|
79 |
|
|
}
|
80 |
|
|
memcpy(cp_table, ptr, 128);
|
81 |
|
|
brelse(bh);
|
82 |
|
|
|
83 |
|
|
/* Try to build lowercasing table from uppercasing one */
|
84 |
|
|
|
85 |
|
|
for (i=128; i<256; i++) cp_table[i]=i;
|
86 |
|
|
for (i=128; i<256; i++) if (cp_table[i-128]!=i && cp_table[i-128]>=128)
|
87 |
|
|
cp_table[cp_table[i-128]] = i;
|
88 |
|
|
|
89 |
|
|
return cp_table;
|
90 |
|
|
}
|
91 |
|
|
|
92 |
|
|
secno *hpfs_load_bitmap_directory(struct super_block *s, secno bmp)
|
93 |
|
|
{
|
94 |
|
|
struct buffer_head *bh;
|
95 |
|
|
int n = (s->s_hpfs_fs_size + 0x200000 - 1) >> 21;
|
96 |
|
|
int i;
|
97 |
|
|
secno *b;
|
98 |
|
|
if (!(b = kmalloc(n * 512, GFP_KERNEL))) {
|
99 |
|
|
printk("HPFS: can't allocate memory for bitmap directory\n");
|
100 |
|
|
return NULL;
|
101 |
|
|
}
|
102 |
|
|
for (i=0;i<n;i++) {
|
103 |
|
|
secno *d = hpfs_map_sector(s, bmp+i, &bh, n - i - 1);
|
104 |
|
|
if (!d) {
|
105 |
|
|
kfree(b);
|
106 |
|
|
return NULL;
|
107 |
|
|
}
|
108 |
|
|
memcpy((char *)b + 512 * i, d, 512);
|
109 |
|
|
brelse(bh);
|
110 |
|
|
}
|
111 |
|
|
return b;
|
112 |
|
|
}
|
113 |
|
|
|
114 |
|
|
/*
|
115 |
|
|
* Load fnode to memory
|
116 |
|
|
*/
|
117 |
|
|
|
118 |
|
|
struct fnode *hpfs_map_fnode(struct super_block *s, ino_t ino, struct buffer_head **bhp)
|
119 |
|
|
{
|
120 |
|
|
struct fnode *fnode;
|
121 |
|
|
if (s->s_hpfs_chk) if (hpfs_chk_sectors(s, ino, 1, "fnode")) {
|
122 |
|
|
return NULL;
|
123 |
|
|
}
|
124 |
|
|
if ((fnode = hpfs_map_sector(s, ino, bhp, FNODE_RD_AHEAD))) {
|
125 |
|
|
if (s->s_hpfs_chk) {
|
126 |
|
|
struct extended_attribute *ea;
|
127 |
|
|
struct extended_attribute *ea_end;
|
128 |
|
|
if (fnode->magic != FNODE_MAGIC) {
|
129 |
|
|
hpfs_error(s, "bad magic on fnode %08x", ino);
|
130 |
|
|
goto bail;
|
131 |
|
|
}
|
132 |
|
|
if (!fnode->dirflag) {
|
133 |
|
|
if ((unsigned)fnode->btree.n_used_nodes + (unsigned)fnode->btree.n_free_nodes !=
|
134 |
|
|
(fnode->btree.internal ? 12 : 8)) {
|
135 |
|
|
hpfs_error(s, "bad number of nodes in fnode %08x", ino);
|
136 |
|
|
goto bail;
|
137 |
|
|
}
|
138 |
|
|
if (fnode->btree.first_free !=
|
139 |
|
|
8 + fnode->btree.n_used_nodes * (fnode->btree.internal ? 8 : 12)) {
|
140 |
|
|
hpfs_error(s, "bad first_free pointer in fnode %08x", ino);
|
141 |
|
|
goto bail;
|
142 |
|
|
}
|
143 |
|
|
}
|
144 |
|
|
if (fnode->ea_size_s && ((signed int)fnode->ea_offs < 0xc4 ||
|
145 |
|
|
(signed int)fnode->ea_offs + fnode->ea_size_s > 0x200)) {
|
146 |
|
|
hpfs_error(s, "bad EA info in fnode %08x: ea_offs == %04x ea_size_s == %04x",
|
147 |
|
|
ino, fnode->ea_offs, fnode->ea_size_s);
|
148 |
|
|
goto bail;
|
149 |
|
|
}
|
150 |
|
|
ea = fnode_ea(fnode);
|
151 |
|
|
ea_end = fnode_end_ea(fnode);
|
152 |
|
|
while (ea != ea_end) {
|
153 |
|
|
if (ea > ea_end) {
|
154 |
|
|
hpfs_error(s, "bad EA in fnode %08x", ino);
|
155 |
|
|
goto bail;
|
156 |
|
|
}
|
157 |
|
|
ea = next_ea(ea);
|
158 |
|
|
}
|
159 |
|
|
}
|
160 |
|
|
}
|
161 |
|
|
return fnode;
|
162 |
|
|
bail:
|
163 |
|
|
brelse(*bhp);
|
164 |
|
|
return NULL;
|
165 |
|
|
}
|
166 |
|
|
|
167 |
|
|
struct anode *hpfs_map_anode(struct super_block *s, anode_secno ano, struct buffer_head **bhp)
|
168 |
|
|
{
|
169 |
|
|
struct anode *anode;
|
170 |
|
|
if (s->s_hpfs_chk) if (hpfs_chk_sectors(s, ano, 1, "anode")) return NULL;
|
171 |
|
|
if ((anode = hpfs_map_sector(s, ano, bhp, ANODE_RD_AHEAD)))
|
172 |
|
|
if (s->s_hpfs_chk) {
|
173 |
|
|
if (anode->magic != ANODE_MAGIC || anode->self != ano) {
|
174 |
|
|
hpfs_error(s, "bad magic on anode %08x", ano);
|
175 |
|
|
goto bail;
|
176 |
|
|
}
|
177 |
|
|
if ((unsigned)anode->btree.n_used_nodes + (unsigned)anode->btree.n_free_nodes !=
|
178 |
|
|
(anode->btree.internal ? 60 : 40)) {
|
179 |
|
|
hpfs_error(s, "bad number of nodes in anode %08x", ano);
|
180 |
|
|
goto bail;
|
181 |
|
|
}
|
182 |
|
|
if (anode->btree.first_free !=
|
183 |
|
|
8 + anode->btree.n_used_nodes * (anode->btree.internal ? 8 : 12)) {
|
184 |
|
|
hpfs_error(s, "bad first_free pointer in anode %08x", ano);
|
185 |
|
|
goto bail;
|
186 |
|
|
}
|
187 |
|
|
}
|
188 |
|
|
return anode;
|
189 |
|
|
bail:
|
190 |
|
|
brelse(*bhp);
|
191 |
|
|
return NULL;
|
192 |
|
|
}
|
193 |
|
|
|
194 |
|
|
/*
|
195 |
|
|
* Load dnode to memory and do some checks
|
196 |
|
|
*/
|
197 |
|
|
|
198 |
|
|
struct dnode *hpfs_map_dnode(struct super_block *s, unsigned secno,
|
199 |
|
|
struct quad_buffer_head *qbh)
|
200 |
|
|
{
|
201 |
|
|
struct dnode *dnode;
|
202 |
|
|
if (s->s_hpfs_chk) {
|
203 |
|
|
if (hpfs_chk_sectors(s, secno, 4, "dnode")) return NULL;
|
204 |
|
|
if (secno & 3) {
|
205 |
|
|
hpfs_error(s, "dnode %08x not byte-aligned", secno);
|
206 |
|
|
return NULL;
|
207 |
|
|
}
|
208 |
|
|
}
|
209 |
|
|
if ((dnode = hpfs_map_4sectors(s, secno, qbh, DNODE_RD_AHEAD)))
|
210 |
|
|
if (s->s_hpfs_chk) {
|
211 |
|
|
unsigned p, pp = 0;
|
212 |
|
|
unsigned char *d = (char *)dnode;
|
213 |
|
|
int b = 0;
|
214 |
|
|
if (dnode->magic != DNODE_MAGIC) {
|
215 |
|
|
hpfs_error(s, "bad magic on dnode %08x", secno);
|
216 |
|
|
goto bail;
|
217 |
|
|
}
|
218 |
|
|
if (dnode->self != secno)
|
219 |
|
|
hpfs_error(s, "bad self pointer on dnode %08x self = %08x", secno, dnode->self);
|
220 |
|
|
/* Check dirents - bad dirents would cause infinite
|
221 |
|
|
loops or shooting to memory */
|
222 |
|
|
if (dnode->first_free > 2048/* || dnode->first_free < 84*/) {
|
223 |
|
|
hpfs_error(s, "dnode %08x has first_free == %08x", secno, dnode->first_free);
|
224 |
|
|
goto bail;
|
225 |
|
|
}
|
226 |
|
|
for (p = 20; p < dnode->first_free; p += d[p] + (d[p+1] << 8)) {
|
227 |
|
|
struct hpfs_dirent *de = (struct hpfs_dirent *)((char *)dnode + p);
|
228 |
|
|
if (de->length > 292 || (de->length < 32) || (de->length & 3)) {
|
229 |
|
|
hpfs_error(s, "bad dirent size in dnode %08x, dirent %03x, last %03x", secno, p, pp);
|
230 |
|
|
goto bail;
|
231 |
|
|
}
|
232 |
|
|
if (((31 + de->namelen + de->down*4 + 3) & ~3) != de->length) {
|
233 |
|
|
hpfs_error(s, "namelen does not match dirent size in dnode %08x, dirent %03x, last %03x", secno, p, pp);
|
234 |
|
|
goto bail;
|
235 |
|
|
}
|
236 |
|
|
if (s->s_hpfs_chk >= 2) b |= 1 << de->down;
|
237 |
|
|
if (de->down) if (de_down_pointer(de) < 0x10) {
|
238 |
|
|
hpfs_error(s, "bad down pointer in dnode %08x, dirent %03x, last %03x", secno, p, pp);
|
239 |
|
|
goto bail;
|
240 |
|
|
}
|
241 |
|
|
pp = p;
|
242 |
|
|
|
243 |
|
|
}
|
244 |
|
|
if (p != dnode->first_free) {
|
245 |
|
|
hpfs_error(s, "size on last dirent does not match first_free; dnode %08x", secno);
|
246 |
|
|
goto bail;
|
247 |
|
|
}
|
248 |
|
|
if (d[pp + 30] != 1 || d[pp + 31] != 255) {
|
249 |
|
|
hpfs_error(s, "dnode %08x does not end with \\377 entry", secno);
|
250 |
|
|
goto bail;
|
251 |
|
|
}
|
252 |
|
|
if (b == 3) printk("HPFS: warning: unbalanced dnode tree, dnode %08x; see hpfs.txt 4 more info\n", secno);
|
253 |
|
|
}
|
254 |
|
|
return dnode;
|
255 |
|
|
bail:
|
256 |
|
|
hpfs_brelse4(qbh);
|
257 |
|
|
return NULL;
|
258 |
|
|
}
|
259 |
|
|
|
260 |
|
|
dnode_secno hpfs_fnode_dno(struct super_block *s, ino_t ino)
|
261 |
|
|
{
|
262 |
|
|
struct buffer_head *bh;
|
263 |
|
|
struct fnode *fnode;
|
264 |
|
|
dnode_secno dno;
|
265 |
|
|
|
266 |
|
|
fnode = hpfs_map_fnode(s, ino, &bh);
|
267 |
|
|
if (!fnode)
|
268 |
|
|
return 0;
|
269 |
|
|
|
270 |
|
|
dno = fnode->u.external[0].disk_secno;
|
271 |
|
|
brelse(bh);
|
272 |
|
|
return dno;
|
273 |
|
|
}
|